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.
4
5 #include "net/http/http_network_transaction.h"
6
7 #include <math.h> // ceil
8 #include <stdarg.h>
9 #include <string>
10 #include <vector>
11
12 #include "base/basictypes.h"
13 #include "base/compiler_specific.h"
14 #include "base/file_util.h"
15 #include "base/files/file_path.h"
16 #include "base/json/json_writer.h"
17 #include "base/memory/scoped_ptr.h"
18 #include "base/memory/weak_ptr.h"
19 #include "base/run_loop.h"
20 #include "base/strings/string_util.h"
21 #include "base/strings/utf_string_conversions.h"
22 #include "base/test/test_file_util.h"
23 #include "net/base/auth.h"
24 #include "net/base/capturing_net_log.h"
25 #include "net/base/completion_callback.h"
26 #include "net/base/load_timing_info.h"
27 #include "net/base/load_timing_info_test_util.h"
28 #include "net/base/net_log.h"
29 #include "net/base/net_log_unittest.h"
30 #include "net/base/request_priority.h"
31 #include "net/base/test_completion_callback.h"
32 #include "net/base/test_data_directory.h"
33 #include "net/base/upload_bytes_element_reader.h"
34 #include "net/base/upload_data_stream.h"
35 #include "net/base/upload_file_element_reader.h"
36 #include "net/cert/mock_cert_verifier.h"
37 #include "net/dns/host_cache.h"
38 #include "net/dns/mock_host_resolver.h"
39 #include "net/http/http_auth_challenge_tokenizer.h"
40 #include "net/http/http_auth_handler_digest.h"
41 #include "net/http/http_auth_handler_mock.h"
42 #include "net/http/http_auth_handler_ntlm.h"
43 #include "net/http/http_basic_stream.h"
44 #include "net/http/http_network_session.h"
45 #include "net/http/http_network_session_peer.h"
46 #include "net/http/http_server_properties_impl.h"
47 #include "net/http/http_stream.h"
48 #include "net/http/http_stream_factory.h"
49 #include "net/http/http_transaction_test_util.h"
50 #include "net/proxy/proxy_config_service_fixed.h"
51 #include "net/proxy/proxy_info.h"
52 #include "net/proxy/proxy_resolver.h"
53 #include "net/proxy/proxy_service.h"
54 #include "net/socket/client_socket_factory.h"
55 #include "net/socket/client_socket_pool_manager.h"
56 #include "net/socket/mock_client_socket_pool_manager.h"
57 #include "net/socket/next_proto.h"
58 #include "net/socket/socket_test_util.h"
59 #include "net/socket/ssl_client_socket.h"
60 #include "net/spdy/spdy_framer.h"
61 #include "net/spdy/spdy_session.h"
62 #include "net/spdy/spdy_session_pool.h"
63 #include "net/spdy/spdy_test_util_common.h"
64 #include "net/ssl/ssl_cert_request_info.h"
65 #include "net/ssl/ssl_config_service.h"
66 #include "net/ssl/ssl_config_service_defaults.h"
67 #include "net/ssl/ssl_info.h"
68 #include "net/test/cert_test_util.h"
69 #include "net/websockets/websocket_handshake_stream_base.h"
70 #include "testing/gtest/include/gtest/gtest.h"
71 #include "testing/platform_test.h"
72 #include "url/gurl.h"
73
74 using base::ASCIIToUTF16;
75
76 //-----------------------------------------------------------------------------
77
78 namespace {
79
80 const base::string16 kBar(ASCIIToUTF16("bar"));
81 const base::string16 kBar2(ASCIIToUTF16("bar2"));
82 const base::string16 kBar3(ASCIIToUTF16("bar3"));
83 const base::string16 kBaz(ASCIIToUTF16("baz"));
84 const base::string16 kFirst(ASCIIToUTF16("first"));
85 const base::string16 kFoo(ASCIIToUTF16("foo"));
86 const base::string16 kFoo2(ASCIIToUTF16("foo2"));
87 const base::string16 kFoo3(ASCIIToUTF16("foo3"));
88 const base::string16 kFou(ASCIIToUTF16("fou"));
89 const base::string16 kSecond(ASCIIToUTF16("second"));
90 const base::string16 kTestingNTLM(ASCIIToUTF16("testing-ntlm"));
91 const base::string16 kWrongPassword(ASCIIToUTF16("wrongpassword"));
92
GetIdleSocketCountInTransportSocketPool(net::HttpNetworkSession * session)93 int GetIdleSocketCountInTransportSocketPool(net::HttpNetworkSession* session) {
94 return session->GetTransportSocketPool(
95 net::HttpNetworkSession::NORMAL_SOCKET_POOL)->IdleSocketCount();
96 }
97
GetIdleSocketCountInSSLSocketPool(net::HttpNetworkSession * session)98 int GetIdleSocketCountInSSLSocketPool(net::HttpNetworkSession* session) {
99 return session->GetSSLSocketPool(
100 net::HttpNetworkSession::NORMAL_SOCKET_POOL)->IdleSocketCount();
101 }
102
IsTransportSocketPoolStalled(net::HttpNetworkSession * session)103 bool IsTransportSocketPoolStalled(net::HttpNetworkSession* session) {
104 return session->GetTransportSocketPool(
105 net::HttpNetworkSession::NORMAL_SOCKET_POOL)->IsStalled();
106 }
107
108 // Takes in a Value created from a NetLogHttpResponseParameter, and returns
109 // a JSONified list of headers as a single string. Uses single quotes instead
110 // of double quotes for easier comparison. Returns false on failure.
GetHeaders(base::DictionaryValue * params,std::string * headers)111 bool GetHeaders(base::DictionaryValue* params, std::string* headers) {
112 if (!params)
113 return false;
114 base::ListValue* header_list;
115 if (!params->GetList("headers", &header_list))
116 return false;
117 std::string double_quote_headers;
118 base::JSONWriter::Write(header_list, &double_quote_headers);
119 base::ReplaceChars(double_quote_headers, "\"", "'", headers);
120 return true;
121 }
122
123 // Tests LoadTimingInfo in the case a socket is reused and no PAC script is
124 // used.
TestLoadTimingReused(const net::LoadTimingInfo & load_timing_info)125 void TestLoadTimingReused(const net::LoadTimingInfo& load_timing_info) {
126 EXPECT_TRUE(load_timing_info.socket_reused);
127 EXPECT_NE(net::NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
128
129 EXPECT_TRUE(load_timing_info.proxy_resolve_start.is_null());
130 EXPECT_TRUE(load_timing_info.proxy_resolve_end.is_null());
131
132 net::ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
133 EXPECT_FALSE(load_timing_info.send_start.is_null());
134
135 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
136
137 // Set at a higher level.
138 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
139 EXPECT_TRUE(load_timing_info.request_start.is_null());
140 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
141 }
142
143 // Tests LoadTimingInfo in the case a new socket is used and no PAC script is
144 // used.
TestLoadTimingNotReused(const net::LoadTimingInfo & load_timing_info,int connect_timing_flags)145 void TestLoadTimingNotReused(const net::LoadTimingInfo& load_timing_info,
146 int connect_timing_flags) {
147 EXPECT_FALSE(load_timing_info.socket_reused);
148 EXPECT_NE(net::NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
149
150 EXPECT_TRUE(load_timing_info.proxy_resolve_start.is_null());
151 EXPECT_TRUE(load_timing_info.proxy_resolve_end.is_null());
152
153 net::ExpectConnectTimingHasTimes(load_timing_info.connect_timing,
154 connect_timing_flags);
155 EXPECT_LE(load_timing_info.connect_timing.connect_end,
156 load_timing_info.send_start);
157
158 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
159
160 // Set at a higher level.
161 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
162 EXPECT_TRUE(load_timing_info.request_start.is_null());
163 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
164 }
165
166 // Tests LoadTimingInfo in the case a socket is reused and a PAC script is
167 // used.
TestLoadTimingReusedWithPac(const net::LoadTimingInfo & load_timing_info)168 void TestLoadTimingReusedWithPac(const net::LoadTimingInfo& load_timing_info) {
169 EXPECT_TRUE(load_timing_info.socket_reused);
170 EXPECT_NE(net::NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
171
172 net::ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
173
174 EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null());
175 EXPECT_LE(load_timing_info.proxy_resolve_start,
176 load_timing_info.proxy_resolve_end);
177 EXPECT_LE(load_timing_info.proxy_resolve_end,
178 load_timing_info.send_start);
179 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
180
181 // Set at a higher level.
182 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
183 EXPECT_TRUE(load_timing_info.request_start.is_null());
184 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
185 }
186
187 // Tests LoadTimingInfo in the case a new socket is used and a PAC script is
188 // used.
TestLoadTimingNotReusedWithPac(const net::LoadTimingInfo & load_timing_info,int connect_timing_flags)189 void TestLoadTimingNotReusedWithPac(const net::LoadTimingInfo& load_timing_info,
190 int connect_timing_flags) {
191 EXPECT_FALSE(load_timing_info.socket_reused);
192 EXPECT_NE(net::NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
193
194 EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null());
195 EXPECT_LE(load_timing_info.proxy_resolve_start,
196 load_timing_info.proxy_resolve_end);
197 EXPECT_LE(load_timing_info.proxy_resolve_end,
198 load_timing_info.connect_timing.connect_start);
199 net::ExpectConnectTimingHasTimes(load_timing_info.connect_timing,
200 connect_timing_flags);
201 EXPECT_LE(load_timing_info.connect_timing.connect_end,
202 load_timing_info.send_start);
203
204 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
205
206 // Set at a higher level.
207 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
208 EXPECT_TRUE(load_timing_info.request_start.is_null());
209 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
210 }
211
212 } // namespace
213
214 namespace net {
215
216 namespace {
217
CreateSession(SpdySessionDependencies * session_deps)218 HttpNetworkSession* CreateSession(SpdySessionDependencies* session_deps) {
219 return SpdySessionDependencies::SpdyCreateSession(session_deps);
220 }
221
222 } // namespace
223
224 class HttpNetworkTransactionTest
225 : public PlatformTest,
226 public ::testing::WithParamInterface<NextProto> {
227 public:
~HttpNetworkTransactionTest()228 virtual ~HttpNetworkTransactionTest() {
229 // Important to restore the per-pool limit first, since the pool limit must
230 // always be greater than group limit, and the tests reduce both limits.
231 ClientSocketPoolManager::set_max_sockets_per_pool(
232 HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_pool_sockets_);
233 ClientSocketPoolManager::set_max_sockets_per_group(
234 HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_group_sockets_);
235 }
236
237 protected:
HttpNetworkTransactionTest()238 HttpNetworkTransactionTest()
239 : spdy_util_(GetParam()),
240 session_deps_(GetParam()),
241 old_max_group_sockets_(ClientSocketPoolManager::max_sockets_per_group(
242 HttpNetworkSession::NORMAL_SOCKET_POOL)),
243 old_max_pool_sockets_(ClientSocketPoolManager::max_sockets_per_pool(
244 HttpNetworkSession::NORMAL_SOCKET_POOL)) {
245 }
246
247 struct SimpleGetHelperResult {
248 int rv;
249 std::string status_line;
250 std::string response_data;
251 int64 totalReceivedBytes;
252 LoadTimingInfo load_timing_info;
253 };
254
SetUp()255 virtual void SetUp() {
256 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
257 base::MessageLoop::current()->RunUntilIdle();
258 }
259
TearDown()260 virtual void TearDown() {
261 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
262 base::MessageLoop::current()->RunUntilIdle();
263 // Empty the current queue.
264 base::MessageLoop::current()->RunUntilIdle();
265 PlatformTest::TearDown();
266 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
267 base::MessageLoop::current()->RunUntilIdle();
268 }
269
270 // This is the expected return from a current server advertising SPDY.
GetAlternateProtocolHttpHeader()271 std::string GetAlternateProtocolHttpHeader() {
272 return
273 std::string("Alternate-Protocol: 443:") +
274 AlternateProtocolToString(AlternateProtocolFromNextProto(GetParam())) +
275 "\r\n\r\n";
276 }
277
278 // Either |write_failure| specifies a write failure or |read_failure|
279 // specifies a read failure when using a reused socket. In either case, the
280 // failure should cause the network transaction to resend the request, and the
281 // other argument should be NULL.
282 void KeepAliveConnectionResendRequestTest(const MockWrite* write_failure,
283 const MockRead* read_failure);
284
285 // Either |write_failure| specifies a write failure or |read_failure|
286 // specifies a read failure when using a reused socket. In either case, the
287 // failure should cause the network transaction to resend the request, and the
288 // other argument should be NULL.
289 void PreconnectErrorResendRequestTest(const MockWrite* write_failure,
290 const MockRead* read_failure,
291 bool use_spdy);
292
SimpleGetHelperForData(StaticSocketDataProvider * data[],size_t data_count)293 SimpleGetHelperResult SimpleGetHelperForData(StaticSocketDataProvider* data[],
294 size_t data_count) {
295 SimpleGetHelperResult out;
296
297 HttpRequestInfo request;
298 request.method = "GET";
299 request.url = GURL("http://www.google.com/");
300 request.load_flags = 0;
301
302 CapturingBoundNetLog log;
303 session_deps_.net_log = log.bound().net_log();
304 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
305 scoped_ptr<HttpTransaction> trans(
306 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
307
308 for (size_t i = 0; i < data_count; ++i) {
309 session_deps_.socket_factory->AddSocketDataProvider(data[i]);
310 }
311
312 TestCompletionCallback callback;
313
314 EXPECT_TRUE(log.bound().IsLogging());
315 int rv = trans->Start(&request, callback.callback(), log.bound());
316 EXPECT_EQ(ERR_IO_PENDING, rv);
317
318 out.rv = callback.WaitForResult();
319
320 // Even in the failure cases that use this function, connections are always
321 // successfully established before the error.
322 EXPECT_TRUE(trans->GetLoadTimingInfo(&out.load_timing_info));
323 TestLoadTimingNotReused(out.load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
324
325 if (out.rv != OK)
326 return out;
327
328 const HttpResponseInfo* response = trans->GetResponseInfo();
329 // Can't use ASSERT_* inside helper functions like this, so
330 // return an error.
331 if (response == NULL || response->headers.get() == NULL) {
332 out.rv = ERR_UNEXPECTED;
333 return out;
334 }
335 out.status_line = response->headers->GetStatusLine();
336
337 EXPECT_EQ("127.0.0.1", response->socket_address.host());
338 EXPECT_EQ(80, response->socket_address.port());
339
340 rv = ReadTransaction(trans.get(), &out.response_data);
341 EXPECT_EQ(OK, rv);
342
343 net::CapturingNetLog::CapturedEntryList entries;
344 log.GetEntries(&entries);
345 size_t pos = ExpectLogContainsSomewhere(
346 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS,
347 NetLog::PHASE_NONE);
348 ExpectLogContainsSomewhere(
349 entries, pos,
350 NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS,
351 NetLog::PHASE_NONE);
352
353 std::string line;
354 EXPECT_TRUE(entries[pos].GetStringValue("line", &line));
355 EXPECT_EQ("GET / HTTP/1.1\r\n", line);
356
357 HttpRequestHeaders request_headers;
358 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
359 std::string value;
360 EXPECT_TRUE(request_headers.GetHeader("Host", &value));
361 EXPECT_EQ("www.google.com", value);
362 EXPECT_TRUE(request_headers.GetHeader("Connection", &value));
363 EXPECT_EQ("keep-alive", value);
364
365 std::string response_headers;
366 EXPECT_TRUE(GetHeaders(entries[pos].params.get(), &response_headers));
367 EXPECT_EQ("['Host: www.google.com','Connection: keep-alive']",
368 response_headers);
369
370 out.totalReceivedBytes = trans->GetTotalReceivedBytes();
371 return out;
372 }
373
SimpleGetHelper(MockRead data_reads[],size_t reads_count)374 SimpleGetHelperResult SimpleGetHelper(MockRead data_reads[],
375 size_t reads_count) {
376 StaticSocketDataProvider reads(data_reads, reads_count, NULL, 0);
377 StaticSocketDataProvider* data[] = { &reads };
378 return SimpleGetHelperForData(data, 1);
379 }
380
ReadsSize(MockRead data_reads[],size_t reads_count)381 int64 ReadsSize(MockRead data_reads[], size_t reads_count) {
382 int64 size = 0;
383 for (size_t i = 0; i < reads_count; ++i)
384 size += data_reads[i].data_len;
385 return size;
386 }
387
388 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
389 int expected_status);
390
391 void ConnectStatusHelper(const MockRead& status);
392
393 void BypassHostCacheOnRefreshHelper(int load_flags);
394
395 void CheckErrorIsPassedBack(int error, IoMode mode);
396
397 SpdyTestUtil spdy_util_;
398 SpdySessionDependencies session_deps_;
399
400 // Original socket limits. Some tests set these. Safest to always restore
401 // them once each test has been run.
402 int old_max_group_sockets_;
403 int old_max_pool_sockets_;
404 };
405
406 INSTANTIATE_TEST_CASE_P(
407 NextProto,
408 HttpNetworkTransactionTest,
409 testing::Values(kProtoDeprecatedSPDY2,
410 kProtoSPDY3, kProtoSPDY31, kProtoSPDY4));
411
412 namespace {
413
414 class BeforeNetworkStartHandler {
415 public:
BeforeNetworkStartHandler(bool defer)416 explicit BeforeNetworkStartHandler(bool defer)
417 : defer_on_before_network_start_(defer),
418 observed_before_network_start_(false) {}
419
OnBeforeNetworkStart(bool * defer)420 void OnBeforeNetworkStart(bool* defer) {
421 *defer = defer_on_before_network_start_;
422 observed_before_network_start_ = true;
423 }
424
observed_before_network_start() const425 bool observed_before_network_start() const {
426 return observed_before_network_start_;
427 }
428
429 private:
430 const bool defer_on_before_network_start_;
431 bool observed_before_network_start_;
432
433 DISALLOW_COPY_AND_ASSIGN(BeforeNetworkStartHandler);
434 };
435
436 // Fill |str| with a long header list that consumes >= |size| bytes.
FillLargeHeadersString(std::string * str,int size)437 void FillLargeHeadersString(std::string* str, int size) {
438 const char* row =
439 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
440 const int sizeof_row = strlen(row);
441 const int num_rows = static_cast<int>(
442 ceil(static_cast<float>(size) / sizeof_row));
443 const int sizeof_data = num_rows * sizeof_row;
444 DCHECK(sizeof_data >= size);
445 str->reserve(sizeof_data);
446
447 for (int i = 0; i < num_rows; ++i)
448 str->append(row, sizeof_row);
449 }
450
451 // Alternative functions that eliminate randomness and dependency on the local
452 // host name so that the generated NTLM messages are reproducible.
MockGenerateRandom1(uint8 * output,size_t n)453 void MockGenerateRandom1(uint8* output, size_t n) {
454 static const uint8 bytes[] = {
455 0x55, 0x29, 0x66, 0x26, 0x6b, 0x9c, 0x73, 0x54
456 };
457 static size_t current_byte = 0;
458 for (size_t i = 0; i < n; ++i) {
459 output[i] = bytes[current_byte++];
460 current_byte %= arraysize(bytes);
461 }
462 }
463
MockGenerateRandom2(uint8 * output,size_t n)464 void MockGenerateRandom2(uint8* output, size_t n) {
465 static const uint8 bytes[] = {
466 0x96, 0x79, 0x85, 0xe7, 0x49, 0x93, 0x70, 0xa1,
467 0x4e, 0xe7, 0x87, 0x45, 0x31, 0x5b, 0xd3, 0x1f
468 };
469 static size_t current_byte = 0;
470 for (size_t i = 0; i < n; ++i) {
471 output[i] = bytes[current_byte++];
472 current_byte %= arraysize(bytes);
473 }
474 }
475
MockGetHostName()476 std::string MockGetHostName() {
477 return "WTC-WIN7";
478 }
479
480 template<typename ParentPool>
481 class CaptureGroupNameSocketPool : public ParentPool {
482 public:
483 CaptureGroupNameSocketPool(HostResolver* host_resolver,
484 CertVerifier* cert_verifier);
485
last_group_name_received() const486 const std::string last_group_name_received() const {
487 return last_group_name_;
488 }
489
RequestSocket(const std::string & group_name,const void * socket_params,RequestPriority priority,ClientSocketHandle * handle,const CompletionCallback & callback,const BoundNetLog & net_log)490 virtual int RequestSocket(const std::string& group_name,
491 const void* socket_params,
492 RequestPriority priority,
493 ClientSocketHandle* handle,
494 const CompletionCallback& callback,
495 const BoundNetLog& net_log) {
496 last_group_name_ = group_name;
497 return ERR_IO_PENDING;
498 }
CancelRequest(const std::string & group_name,ClientSocketHandle * handle)499 virtual void CancelRequest(const std::string& group_name,
500 ClientSocketHandle* handle) {}
ReleaseSocket(const std::string & group_name,scoped_ptr<StreamSocket> socket,int id)501 virtual void ReleaseSocket(const std::string& group_name,
502 scoped_ptr<StreamSocket> socket,
503 int id) {}
CloseIdleSockets()504 virtual void CloseIdleSockets() {}
IdleSocketCount() const505 virtual int IdleSocketCount() const {
506 return 0;
507 }
IdleSocketCountInGroup(const std::string & group_name) const508 virtual int IdleSocketCountInGroup(const std::string& group_name) const {
509 return 0;
510 }
GetLoadState(const std::string & group_name,const ClientSocketHandle * handle) const511 virtual LoadState GetLoadState(const std::string& group_name,
512 const ClientSocketHandle* handle) const {
513 return LOAD_STATE_IDLE;
514 }
ConnectionTimeout() const515 virtual base::TimeDelta ConnectionTimeout() const {
516 return base::TimeDelta();
517 }
518
519 private:
520 std::string last_group_name_;
521 };
522
523 typedef CaptureGroupNameSocketPool<TransportClientSocketPool>
524 CaptureGroupNameTransportSocketPool;
525 typedef CaptureGroupNameSocketPool<HttpProxyClientSocketPool>
526 CaptureGroupNameHttpProxySocketPool;
527 typedef CaptureGroupNameSocketPool<SOCKSClientSocketPool>
528 CaptureGroupNameSOCKSSocketPool;
529 typedef CaptureGroupNameSocketPool<SSLClientSocketPool>
530 CaptureGroupNameSSLSocketPool;
531
532 template<typename ParentPool>
CaptureGroupNameSocketPool(HostResolver * host_resolver,CertVerifier *)533 CaptureGroupNameSocketPool<ParentPool>::CaptureGroupNameSocketPool(
534 HostResolver* host_resolver,
535 CertVerifier* /* cert_verifier */)
536 : ParentPool(0, 0, NULL, host_resolver, NULL, NULL) {}
537
538 template<>
CaptureGroupNameSocketPool(HostResolver * host_resolver,CertVerifier *)539 CaptureGroupNameHttpProxySocketPool::CaptureGroupNameSocketPool(
540 HostResolver* host_resolver,
541 CertVerifier* /* cert_verifier */)
542 : HttpProxyClientSocketPool(0, 0, NULL, host_resolver, NULL, NULL, NULL) {}
543
544 template <>
CaptureGroupNameSocketPool(HostResolver * host_resolver,CertVerifier * cert_verifier)545 CaptureGroupNameSSLSocketPool::CaptureGroupNameSocketPool(
546 HostResolver* host_resolver,
547 CertVerifier* cert_verifier)
548 : SSLClientSocketPool(0,
549 0,
550 NULL,
551 host_resolver,
552 cert_verifier,
553 NULL,
554 NULL,
555 NULL,
556 std::string(),
557 NULL,
558 NULL,
559 NULL,
560 NULL,
561 NULL,
562 NULL) {}
563
564 //-----------------------------------------------------------------------------
565
566 // Helper functions for validating that AuthChallengeInfo's are correctly
567 // configured for common cases.
CheckBasicServerAuth(const AuthChallengeInfo * auth_challenge)568 bool CheckBasicServerAuth(const AuthChallengeInfo* auth_challenge) {
569 if (!auth_challenge)
570 return false;
571 EXPECT_FALSE(auth_challenge->is_proxy);
572 EXPECT_EQ("www.google.com:80", auth_challenge->challenger.ToString());
573 EXPECT_EQ("MyRealm1", auth_challenge->realm);
574 EXPECT_EQ("basic", auth_challenge->scheme);
575 return true;
576 }
577
CheckBasicProxyAuth(const AuthChallengeInfo * auth_challenge)578 bool CheckBasicProxyAuth(const AuthChallengeInfo* auth_challenge) {
579 if (!auth_challenge)
580 return false;
581 EXPECT_TRUE(auth_challenge->is_proxy);
582 EXPECT_EQ("myproxy:70", auth_challenge->challenger.ToString());
583 EXPECT_EQ("MyRealm1", auth_challenge->realm);
584 EXPECT_EQ("basic", auth_challenge->scheme);
585 return true;
586 }
587
CheckDigestServerAuth(const AuthChallengeInfo * auth_challenge)588 bool CheckDigestServerAuth(const AuthChallengeInfo* auth_challenge) {
589 if (!auth_challenge)
590 return false;
591 EXPECT_FALSE(auth_challenge->is_proxy);
592 EXPECT_EQ("www.google.com:80", auth_challenge->challenger.ToString());
593 EXPECT_EQ("digestive", auth_challenge->realm);
594 EXPECT_EQ("digest", auth_challenge->scheme);
595 return true;
596 }
597
CheckNTLMServerAuth(const AuthChallengeInfo * auth_challenge)598 bool CheckNTLMServerAuth(const AuthChallengeInfo* auth_challenge) {
599 if (!auth_challenge)
600 return false;
601 EXPECT_FALSE(auth_challenge->is_proxy);
602 EXPECT_EQ("172.22.68.17:80", auth_challenge->challenger.ToString());
603 EXPECT_EQ(std::string(), auth_challenge->realm);
604 EXPECT_EQ("ntlm", auth_challenge->scheme);
605 return true;
606 }
607
608 } // namespace
609
TEST_P(HttpNetworkTransactionTest,Basic)610 TEST_P(HttpNetworkTransactionTest, Basic) {
611 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
612 scoped_ptr<HttpTransaction> trans(
613 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
614 }
615
TEST_P(HttpNetworkTransactionTest,SimpleGET)616 TEST_P(HttpNetworkTransactionTest, SimpleGET) {
617 MockRead data_reads[] = {
618 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
619 MockRead("hello world"),
620 MockRead(SYNCHRONOUS, OK),
621 };
622 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
623 arraysize(data_reads));
624 EXPECT_EQ(OK, out.rv);
625 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
626 EXPECT_EQ("hello world", out.response_data);
627 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
628 EXPECT_EQ(reads_size, out.totalReceivedBytes);
629 }
630
631 // Response with no status line.
TEST_P(HttpNetworkTransactionTest,SimpleGETNoHeaders)632 TEST_P(HttpNetworkTransactionTest, SimpleGETNoHeaders) {
633 MockRead data_reads[] = {
634 MockRead("hello world"),
635 MockRead(SYNCHRONOUS, OK),
636 };
637 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
638 arraysize(data_reads));
639 EXPECT_EQ(OK, out.rv);
640 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
641 EXPECT_EQ("hello world", out.response_data);
642 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
643 EXPECT_EQ(reads_size, out.totalReceivedBytes);
644 }
645
646 // Allow up to 4 bytes of junk to precede status line.
TEST_P(HttpNetworkTransactionTest,StatusLineJunk3Bytes)647 TEST_P(HttpNetworkTransactionTest, StatusLineJunk3Bytes) {
648 MockRead data_reads[] = {
649 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
650 MockRead(SYNCHRONOUS, OK),
651 };
652 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
653 arraysize(data_reads));
654 EXPECT_EQ(OK, out.rv);
655 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
656 EXPECT_EQ("DATA", out.response_data);
657 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
658 EXPECT_EQ(reads_size, out.totalReceivedBytes);
659 }
660
661 // Allow up to 4 bytes of junk to precede status line.
TEST_P(HttpNetworkTransactionTest,StatusLineJunk4Bytes)662 TEST_P(HttpNetworkTransactionTest, StatusLineJunk4Bytes) {
663 MockRead data_reads[] = {
664 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
665 MockRead(SYNCHRONOUS, OK),
666 };
667 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
668 arraysize(data_reads));
669 EXPECT_EQ(OK, out.rv);
670 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
671 EXPECT_EQ("DATA", out.response_data);
672 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
673 EXPECT_EQ(reads_size, out.totalReceivedBytes);
674 }
675
676 // Beyond 4 bytes of slop and it should fail to find a status line.
TEST_P(HttpNetworkTransactionTest,StatusLineJunk5Bytes)677 TEST_P(HttpNetworkTransactionTest, StatusLineJunk5Bytes) {
678 MockRead data_reads[] = {
679 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
680 MockRead(SYNCHRONOUS, OK),
681 };
682 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
683 arraysize(data_reads));
684 EXPECT_EQ(OK, out.rv);
685 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
686 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data);
687 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
688 EXPECT_EQ(reads_size, out.totalReceivedBytes);
689 }
690
691 // Same as StatusLineJunk4Bytes, except the read chunks are smaller.
TEST_P(HttpNetworkTransactionTest,StatusLineJunk4Bytes_Slow)692 TEST_P(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) {
693 MockRead data_reads[] = {
694 MockRead("\n"),
695 MockRead("\n"),
696 MockRead("Q"),
697 MockRead("J"),
698 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
699 MockRead(SYNCHRONOUS, OK),
700 };
701 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
702 arraysize(data_reads));
703 EXPECT_EQ(OK, out.rv);
704 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
705 EXPECT_EQ("DATA", out.response_data);
706 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
707 EXPECT_EQ(reads_size, out.totalReceivedBytes);
708 }
709
710 // Close the connection before enough bytes to have a status line.
TEST_P(HttpNetworkTransactionTest,StatusLinePartial)711 TEST_P(HttpNetworkTransactionTest, StatusLinePartial) {
712 MockRead data_reads[] = {
713 MockRead("HTT"),
714 MockRead(SYNCHRONOUS, OK),
715 };
716 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
717 arraysize(data_reads));
718 EXPECT_EQ(OK, out.rv);
719 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
720 EXPECT_EQ("HTT", out.response_data);
721 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
722 EXPECT_EQ(reads_size, out.totalReceivedBytes);
723 }
724
725 // Simulate a 204 response, lacking a Content-Length header, sent over a
726 // persistent connection. The response should still terminate since a 204
727 // cannot have a response body.
TEST_P(HttpNetworkTransactionTest,StopsReading204)728 TEST_P(HttpNetworkTransactionTest, StopsReading204) {
729 char junk[] = "junk";
730 MockRead data_reads[] = {
731 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
732 MockRead(junk), // Should not be read!!
733 MockRead(SYNCHRONOUS, OK),
734 };
735 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
736 arraysize(data_reads));
737 EXPECT_EQ(OK, out.rv);
738 EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line);
739 EXPECT_EQ("", out.response_data);
740 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
741 int64 response_size = reads_size - strlen(junk);
742 EXPECT_EQ(response_size, out.totalReceivedBytes);
743 }
744
745 // A simple request using chunked encoding with some extra data after.
TEST_P(HttpNetworkTransactionTest,ChunkedEncoding)746 TEST_P(HttpNetworkTransactionTest, ChunkedEncoding) {
747 std::string final_chunk = "0\r\n\r\n";
748 std::string extra_data = "HTTP/1.1 200 OK\r\n";
749 std::string last_read = final_chunk + extra_data;
750 MockRead data_reads[] = {
751 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
752 MockRead("5\r\nHello\r\n"),
753 MockRead("1\r\n"),
754 MockRead(" \r\n"),
755 MockRead("5\r\nworld\r\n"),
756 MockRead(last_read.data()),
757 MockRead(SYNCHRONOUS, OK),
758 };
759 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
760 arraysize(data_reads));
761 EXPECT_EQ(OK, out.rv);
762 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
763 EXPECT_EQ("Hello world", out.response_data);
764 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
765 int64 response_size = reads_size - extra_data.size();
766 EXPECT_EQ(response_size, out.totalReceivedBytes);
767 }
768
769 // Next tests deal with http://crbug.com/56344.
770
TEST_P(HttpNetworkTransactionTest,MultipleContentLengthHeadersNoTransferEncoding)771 TEST_P(HttpNetworkTransactionTest,
772 MultipleContentLengthHeadersNoTransferEncoding) {
773 MockRead data_reads[] = {
774 MockRead("HTTP/1.1 200 OK\r\n"),
775 MockRead("Content-Length: 10\r\n"),
776 MockRead("Content-Length: 5\r\n\r\n"),
777 };
778 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
779 arraysize(data_reads));
780 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, out.rv);
781 }
782
TEST_P(HttpNetworkTransactionTest,DuplicateContentLengthHeadersNoTransferEncoding)783 TEST_P(HttpNetworkTransactionTest,
784 DuplicateContentLengthHeadersNoTransferEncoding) {
785 MockRead data_reads[] = {
786 MockRead("HTTP/1.1 200 OK\r\n"),
787 MockRead("Content-Length: 5\r\n"),
788 MockRead("Content-Length: 5\r\n\r\n"),
789 MockRead("Hello"),
790 };
791 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
792 arraysize(data_reads));
793 EXPECT_EQ(OK, out.rv);
794 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
795 EXPECT_EQ("Hello", out.response_data);
796 }
797
TEST_P(HttpNetworkTransactionTest,ComplexContentLengthHeadersNoTransferEncoding)798 TEST_P(HttpNetworkTransactionTest,
799 ComplexContentLengthHeadersNoTransferEncoding) {
800 // More than 2 dupes.
801 {
802 MockRead data_reads[] = {
803 MockRead("HTTP/1.1 200 OK\r\n"),
804 MockRead("Content-Length: 5\r\n"),
805 MockRead("Content-Length: 5\r\n"),
806 MockRead("Content-Length: 5\r\n\r\n"),
807 MockRead("Hello"),
808 };
809 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
810 arraysize(data_reads));
811 EXPECT_EQ(OK, out.rv);
812 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
813 EXPECT_EQ("Hello", out.response_data);
814 }
815 // HTTP/1.0
816 {
817 MockRead data_reads[] = {
818 MockRead("HTTP/1.0 200 OK\r\n"),
819 MockRead("Content-Length: 5\r\n"),
820 MockRead("Content-Length: 5\r\n"),
821 MockRead("Content-Length: 5\r\n\r\n"),
822 MockRead("Hello"),
823 };
824 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
825 arraysize(data_reads));
826 EXPECT_EQ(OK, out.rv);
827 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
828 EXPECT_EQ("Hello", out.response_data);
829 }
830 // 2 dupes and one mismatched.
831 {
832 MockRead data_reads[] = {
833 MockRead("HTTP/1.1 200 OK\r\n"),
834 MockRead("Content-Length: 10\r\n"),
835 MockRead("Content-Length: 10\r\n"),
836 MockRead("Content-Length: 5\r\n\r\n"),
837 };
838 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
839 arraysize(data_reads));
840 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, out.rv);
841 }
842 }
843
TEST_P(HttpNetworkTransactionTest,MultipleContentLengthHeadersTransferEncoding)844 TEST_P(HttpNetworkTransactionTest,
845 MultipleContentLengthHeadersTransferEncoding) {
846 MockRead data_reads[] = {
847 MockRead("HTTP/1.1 200 OK\r\n"),
848 MockRead("Content-Length: 666\r\n"),
849 MockRead("Content-Length: 1337\r\n"),
850 MockRead("Transfer-Encoding: chunked\r\n\r\n"),
851 MockRead("5\r\nHello\r\n"),
852 MockRead("1\r\n"),
853 MockRead(" \r\n"),
854 MockRead("5\r\nworld\r\n"),
855 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
856 MockRead(SYNCHRONOUS, OK),
857 };
858 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
859 arraysize(data_reads));
860 EXPECT_EQ(OK, out.rv);
861 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
862 EXPECT_EQ("Hello world", out.response_data);
863 }
864
865 // Next tests deal with http://crbug.com/98895.
866
867 // Checks that a single Content-Disposition header results in no error.
TEST_P(HttpNetworkTransactionTest,SingleContentDispositionHeader)868 TEST_P(HttpNetworkTransactionTest, SingleContentDispositionHeader) {
869 MockRead data_reads[] = {
870 MockRead("HTTP/1.1 200 OK\r\n"),
871 MockRead("Content-Disposition: attachment;filename=\"salutations.txt\"r\n"),
872 MockRead("Content-Length: 5\r\n\r\n"),
873 MockRead("Hello"),
874 };
875 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
876 arraysize(data_reads));
877 EXPECT_EQ(OK, out.rv);
878 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
879 EXPECT_EQ("Hello", out.response_data);
880 }
881
882 // Checks that two identical Content-Disposition headers result in no error.
TEST_P(HttpNetworkTransactionTest,TwoIdenticalContentDispositionHeaders)883 TEST_P(HttpNetworkTransactionTest,
884 TwoIdenticalContentDispositionHeaders) {
885 MockRead data_reads[] = {
886 MockRead("HTTP/1.1 200 OK\r\n"),
887 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
888 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
889 MockRead("Content-Length: 5\r\n\r\n"),
890 MockRead("Hello"),
891 };
892 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
893 arraysize(data_reads));
894 EXPECT_EQ(OK, out.rv);
895 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
896 EXPECT_EQ("Hello", out.response_data);
897 }
898
899 // Checks that two distinct Content-Disposition headers result in an error.
TEST_P(HttpNetworkTransactionTest,TwoDistinctContentDispositionHeaders)900 TEST_P(HttpNetworkTransactionTest, TwoDistinctContentDispositionHeaders) {
901 MockRead data_reads[] = {
902 MockRead("HTTP/1.1 200 OK\r\n"),
903 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
904 MockRead("Content-Disposition: attachment;filename=\"hi.txt\"r\n"),
905 MockRead("Content-Length: 5\r\n\r\n"),
906 MockRead("Hello"),
907 };
908 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
909 arraysize(data_reads));
910 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION, out.rv);
911 }
912
913 // Checks that two identical Location headers result in no error.
914 // Also tests Location header behavior.
TEST_P(HttpNetworkTransactionTest,TwoIdenticalLocationHeaders)915 TEST_P(HttpNetworkTransactionTest, TwoIdenticalLocationHeaders) {
916 MockRead data_reads[] = {
917 MockRead("HTTP/1.1 302 Redirect\r\n"),
918 MockRead("Location: http://good.com/\r\n"),
919 MockRead("Location: http://good.com/\r\n"),
920 MockRead("Content-Length: 0\r\n\r\n"),
921 MockRead(SYNCHRONOUS, OK),
922 };
923
924 HttpRequestInfo request;
925 request.method = "GET";
926 request.url = GURL("http://redirect.com/");
927 request.load_flags = 0;
928
929 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
930 scoped_ptr<HttpTransaction> trans(
931 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
932
933 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
934 session_deps_.socket_factory->AddSocketDataProvider(&data);
935
936 TestCompletionCallback callback;
937
938 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
939 EXPECT_EQ(ERR_IO_PENDING, rv);
940
941 EXPECT_EQ(OK, callback.WaitForResult());
942
943 const HttpResponseInfo* response = trans->GetResponseInfo();
944 ASSERT_TRUE(response != NULL && response->headers.get() != NULL);
945 EXPECT_EQ("HTTP/1.1 302 Redirect", response->headers->GetStatusLine());
946 std::string url;
947 EXPECT_TRUE(response->headers->IsRedirect(&url));
948 EXPECT_EQ("http://good.com/", url);
949 EXPECT_TRUE(response->proxy_server.IsEmpty());
950 }
951
952 // Checks that two distinct Location headers result in an error.
TEST_P(HttpNetworkTransactionTest,TwoDistinctLocationHeaders)953 TEST_P(HttpNetworkTransactionTest, TwoDistinctLocationHeaders) {
954 MockRead data_reads[] = {
955 MockRead("HTTP/1.1 302 Redirect\r\n"),
956 MockRead("Location: http://good.com/\r\n"),
957 MockRead("Location: http://evil.com/\r\n"),
958 MockRead("Content-Length: 0\r\n\r\n"),
959 MockRead(SYNCHRONOUS, OK),
960 };
961 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
962 arraysize(data_reads));
963 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_LOCATION, out.rv);
964 }
965
966 // Do a request using the HEAD method. Verify that we don't try to read the
967 // message body (since HEAD has none).
TEST_P(HttpNetworkTransactionTest,Head)968 TEST_P(HttpNetworkTransactionTest, Head) {
969 HttpRequestInfo request;
970 request.method = "HEAD";
971 request.url = GURL("http://www.google.com/");
972 request.load_flags = 0;
973
974 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
975 scoped_ptr<HttpTransaction> trans(
976 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
977
978 MockWrite data_writes1[] = {
979 MockWrite("HEAD / HTTP/1.1\r\n"
980 "Host: www.google.com\r\n"
981 "Connection: keep-alive\r\n"
982 "Content-Length: 0\r\n\r\n"),
983 };
984 MockRead data_reads1[] = {
985 MockRead("HTTP/1.1 404 Not Found\r\n"),
986 MockRead("Server: Blah\r\n"),
987 MockRead("Content-Length: 1234\r\n\r\n"),
988
989 // No response body because the test stops reading here.
990 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
991 };
992
993 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
994 data_writes1, arraysize(data_writes1));
995 session_deps_.socket_factory->AddSocketDataProvider(&data1);
996
997 TestCompletionCallback callback1;
998
999 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
1000 EXPECT_EQ(ERR_IO_PENDING, rv);
1001
1002 rv = callback1.WaitForResult();
1003 EXPECT_EQ(OK, rv);
1004
1005 const HttpResponseInfo* response = trans->GetResponseInfo();
1006 ASSERT_TRUE(response != NULL);
1007
1008 // Check that the headers got parsed.
1009 EXPECT_TRUE(response->headers.get() != NULL);
1010 EXPECT_EQ(1234, response->headers->GetContentLength());
1011 EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine());
1012 EXPECT_TRUE(response->proxy_server.IsEmpty());
1013
1014 std::string server_header;
1015 void* iter = NULL;
1016 bool has_server_header = response->headers->EnumerateHeader(
1017 &iter, "Server", &server_header);
1018 EXPECT_TRUE(has_server_header);
1019 EXPECT_EQ("Blah", server_header);
1020
1021 // Reading should give EOF right away, since there is no message body
1022 // (despite non-zero content-length).
1023 std::string response_data;
1024 rv = ReadTransaction(trans.get(), &response_data);
1025 EXPECT_EQ(OK, rv);
1026 EXPECT_EQ("", response_data);
1027 }
1028
TEST_P(HttpNetworkTransactionTest,ReuseConnection)1029 TEST_P(HttpNetworkTransactionTest, ReuseConnection) {
1030 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1031
1032 MockRead data_reads[] = {
1033 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1034 MockRead("hello"),
1035 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1036 MockRead("world"),
1037 MockRead(SYNCHRONOUS, OK),
1038 };
1039 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1040 session_deps_.socket_factory->AddSocketDataProvider(&data);
1041
1042 const char* const kExpectedResponseData[] = {
1043 "hello", "world"
1044 };
1045
1046 for (int i = 0; i < 2; ++i) {
1047 HttpRequestInfo request;
1048 request.method = "GET";
1049 request.url = GURL("http://www.google.com/");
1050 request.load_flags = 0;
1051
1052 scoped_ptr<HttpTransaction> trans(
1053 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1054
1055 TestCompletionCallback callback;
1056
1057 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1058 EXPECT_EQ(ERR_IO_PENDING, rv);
1059
1060 rv = callback.WaitForResult();
1061 EXPECT_EQ(OK, rv);
1062
1063 const HttpResponseInfo* response = trans->GetResponseInfo();
1064 ASSERT_TRUE(response != NULL);
1065
1066 EXPECT_TRUE(response->headers.get() != NULL);
1067 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1068 EXPECT_TRUE(response->proxy_server.IsEmpty());
1069
1070 std::string response_data;
1071 rv = ReadTransaction(trans.get(), &response_data);
1072 EXPECT_EQ(OK, rv);
1073 EXPECT_EQ(kExpectedResponseData[i], response_data);
1074 }
1075 }
1076
TEST_P(HttpNetworkTransactionTest,Ignores100)1077 TEST_P(HttpNetworkTransactionTest, Ignores100) {
1078 ScopedVector<UploadElementReader> element_readers;
1079 element_readers.push_back(new UploadBytesElementReader("foo", 3));
1080 UploadDataStream upload_data_stream(element_readers.Pass(), 0);
1081
1082 HttpRequestInfo request;
1083 request.method = "POST";
1084 request.url = GURL("http://www.foo.com/");
1085 request.upload_data_stream = &upload_data_stream;
1086 request.load_flags = 0;
1087
1088 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1089 scoped_ptr<HttpTransaction> trans(
1090 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
1091
1092 MockRead data_reads[] = {
1093 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
1094 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
1095 MockRead("hello world"),
1096 MockRead(SYNCHRONOUS, OK),
1097 };
1098 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1099 session_deps_.socket_factory->AddSocketDataProvider(&data);
1100
1101 TestCompletionCallback callback;
1102
1103 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1104 EXPECT_EQ(ERR_IO_PENDING, rv);
1105
1106 rv = callback.WaitForResult();
1107 EXPECT_EQ(OK, rv);
1108
1109 const HttpResponseInfo* response = trans->GetResponseInfo();
1110 ASSERT_TRUE(response != NULL);
1111
1112 EXPECT_TRUE(response->headers.get() != NULL);
1113 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
1114
1115 std::string response_data;
1116 rv = ReadTransaction(trans.get(), &response_data);
1117 EXPECT_EQ(OK, rv);
1118 EXPECT_EQ("hello world", response_data);
1119 }
1120
1121 // This test is almost the same as Ignores100 above, but the response contains
1122 // a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
1123 // HTTP/1.1 and the two status headers are read in one read.
TEST_P(HttpNetworkTransactionTest,Ignores1xx)1124 TEST_P(HttpNetworkTransactionTest, Ignores1xx) {
1125 HttpRequestInfo request;
1126 request.method = "GET";
1127 request.url = GURL("http://www.foo.com/");
1128 request.load_flags = 0;
1129
1130 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1131 scoped_ptr<HttpTransaction> trans(
1132 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
1133
1134 MockRead data_reads[] = {
1135 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
1136 "HTTP/1.1 200 OK\r\n\r\n"),
1137 MockRead("hello world"),
1138 MockRead(SYNCHRONOUS, OK),
1139 };
1140 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1141 session_deps_.socket_factory->AddSocketDataProvider(&data);
1142
1143 TestCompletionCallback callback;
1144
1145 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1146 EXPECT_EQ(ERR_IO_PENDING, rv);
1147
1148 rv = callback.WaitForResult();
1149 EXPECT_EQ(OK, rv);
1150
1151 const HttpResponseInfo* response = trans->GetResponseInfo();
1152 ASSERT_TRUE(response != NULL);
1153
1154 EXPECT_TRUE(response->headers.get() != NULL);
1155 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1156
1157 std::string response_data;
1158 rv = ReadTransaction(trans.get(), &response_data);
1159 EXPECT_EQ(OK, rv);
1160 EXPECT_EQ("hello world", response_data);
1161 }
1162
TEST_P(HttpNetworkTransactionTest,Incomplete100ThenEOF)1163 TEST_P(HttpNetworkTransactionTest, Incomplete100ThenEOF) {
1164 HttpRequestInfo request;
1165 request.method = "POST";
1166 request.url = GURL("http://www.foo.com/");
1167 request.load_flags = 0;
1168
1169 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1170 scoped_ptr<HttpTransaction> trans(
1171 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
1172
1173 MockRead data_reads[] = {
1174 MockRead(SYNCHRONOUS, "HTTP/1.0 100 Continue\r\n"),
1175 MockRead(ASYNC, 0),
1176 };
1177 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1178 session_deps_.socket_factory->AddSocketDataProvider(&data);
1179
1180 TestCompletionCallback callback;
1181
1182 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1183 EXPECT_EQ(ERR_IO_PENDING, rv);
1184
1185 rv = callback.WaitForResult();
1186 EXPECT_EQ(OK, rv);
1187
1188 std::string response_data;
1189 rv = ReadTransaction(trans.get(), &response_data);
1190 EXPECT_EQ(OK, rv);
1191 EXPECT_EQ("", response_data);
1192 }
1193
TEST_P(HttpNetworkTransactionTest,EmptyResponse)1194 TEST_P(HttpNetworkTransactionTest, EmptyResponse) {
1195 HttpRequestInfo request;
1196 request.method = "POST";
1197 request.url = GURL("http://www.foo.com/");
1198 request.load_flags = 0;
1199
1200 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1201 scoped_ptr<HttpTransaction> trans(
1202 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
1203
1204
1205 MockRead data_reads[] = {
1206 MockRead(ASYNC, 0),
1207 };
1208 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1209 session_deps_.socket_factory->AddSocketDataProvider(&data);
1210
1211 TestCompletionCallback callback;
1212
1213 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1214 EXPECT_EQ(ERR_IO_PENDING, rv);
1215
1216 rv = callback.WaitForResult();
1217 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
1218 }
1219
KeepAliveConnectionResendRequestTest(const MockWrite * write_failure,const MockRead * read_failure)1220 void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
1221 const MockWrite* write_failure,
1222 const MockRead* read_failure) {
1223 HttpRequestInfo request;
1224 request.method = "GET";
1225 request.url = GURL("http://www.foo.com/");
1226 request.load_flags = 0;
1227
1228 CapturingNetLog net_log;
1229 session_deps_.net_log = &net_log;
1230 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1231
1232 // Written data for successfully sending both requests.
1233 MockWrite data1_writes[] = {
1234 MockWrite("GET / HTTP/1.1\r\n"
1235 "Host: www.foo.com\r\n"
1236 "Connection: keep-alive\r\n\r\n"),
1237 MockWrite("GET / HTTP/1.1\r\n"
1238 "Host: www.foo.com\r\n"
1239 "Connection: keep-alive\r\n\r\n")
1240 };
1241
1242 // Read results for the first request.
1243 MockRead data1_reads[] = {
1244 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1245 MockRead("hello"),
1246 MockRead(ASYNC, OK),
1247 };
1248
1249 if (write_failure) {
1250 ASSERT_FALSE(read_failure);
1251 data1_writes[1] = *write_failure;
1252 } else {
1253 ASSERT_TRUE(read_failure);
1254 data1_reads[2] = *read_failure;
1255 }
1256
1257 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads),
1258 data1_writes, arraysize(data1_writes));
1259 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1260
1261 MockRead data2_reads[] = {
1262 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1263 MockRead("world"),
1264 MockRead(ASYNC, OK),
1265 };
1266 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
1267 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1268
1269 const char* kExpectedResponseData[] = {
1270 "hello", "world"
1271 };
1272
1273 uint32 first_socket_log_id = NetLog::Source::kInvalidId;
1274 for (int i = 0; i < 2; ++i) {
1275 TestCompletionCallback callback;
1276
1277 scoped_ptr<HttpTransaction> trans(
1278 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1279
1280 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1281 EXPECT_EQ(ERR_IO_PENDING, rv);
1282
1283 rv = callback.WaitForResult();
1284 EXPECT_EQ(OK, rv);
1285
1286 LoadTimingInfo load_timing_info;
1287 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
1288 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
1289 if (i == 0) {
1290 first_socket_log_id = load_timing_info.socket_log_id;
1291 } else {
1292 // The second request should be using a new socket.
1293 EXPECT_NE(first_socket_log_id, load_timing_info.socket_log_id);
1294 }
1295
1296 const HttpResponseInfo* response = trans->GetResponseInfo();
1297 ASSERT_TRUE(response != NULL);
1298
1299 EXPECT_TRUE(response->headers.get() != NULL);
1300 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1301
1302 std::string response_data;
1303 rv = ReadTransaction(trans.get(), &response_data);
1304 EXPECT_EQ(OK, rv);
1305 EXPECT_EQ(kExpectedResponseData[i], response_data);
1306 }
1307 }
1308
PreconnectErrorResendRequestTest(const MockWrite * write_failure,const MockRead * read_failure,bool use_spdy)1309 void HttpNetworkTransactionTest::PreconnectErrorResendRequestTest(
1310 const MockWrite* write_failure,
1311 const MockRead* read_failure,
1312 bool use_spdy) {
1313 HttpRequestInfo request;
1314 request.method = "GET";
1315 request.url = GURL("https://www.foo.com/");
1316 request.load_flags = 0;
1317
1318 CapturingNetLog net_log;
1319 session_deps_.net_log = &net_log;
1320 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1321
1322 SSLSocketDataProvider ssl1(ASYNC, OK);
1323 SSLSocketDataProvider ssl2(ASYNC, OK);
1324 if (use_spdy) {
1325 ssl1.SetNextProto(GetParam());
1326 ssl2.SetNextProto(GetParam());
1327 }
1328 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
1329 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
1330
1331 // SPDY versions of the request and response.
1332 scoped_ptr<SpdyFrame> spdy_request(spdy_util_.ConstructSpdyGet(
1333 request.url.spec().c_str(), false, 1, DEFAULT_PRIORITY));
1334 scoped_ptr<SpdyFrame> spdy_response(
1335 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1336 scoped_ptr<SpdyFrame> spdy_data(
1337 spdy_util_.ConstructSpdyBodyFrame(1, "hello", 5, true));
1338
1339 // HTTP/1.1 versions of the request and response.
1340 const char kHttpRequest[] = "GET / HTTP/1.1\r\n"
1341 "Host: www.foo.com\r\n"
1342 "Connection: keep-alive\r\n\r\n";
1343 const char kHttpResponse[] = "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n";
1344 const char kHttpData[] = "hello";
1345
1346 std::vector<MockRead> data1_reads;
1347 std::vector<MockWrite> data1_writes;
1348 if (write_failure) {
1349 ASSERT_FALSE(read_failure);
1350 data1_writes.push_back(*write_failure);
1351 data1_reads.push_back(MockRead(ASYNC, OK));
1352 } else {
1353 ASSERT_TRUE(read_failure);
1354 if (use_spdy) {
1355 data1_writes.push_back(CreateMockWrite(*spdy_request));
1356 } else {
1357 data1_writes.push_back(MockWrite(kHttpRequest));
1358 }
1359 data1_reads.push_back(*read_failure);
1360 }
1361
1362 StaticSocketDataProvider data1(&data1_reads[0], data1_reads.size(),
1363 &data1_writes[0], data1_writes.size());
1364 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1365
1366 std::vector<MockRead> data2_reads;
1367 std::vector<MockWrite> data2_writes;
1368
1369 if (use_spdy) {
1370 data2_writes.push_back(CreateMockWrite(*spdy_request, 0, ASYNC));
1371
1372 data2_reads.push_back(CreateMockRead(*spdy_response, 1, ASYNC));
1373 data2_reads.push_back(CreateMockRead(*spdy_data, 2, ASYNC));
1374 data2_reads.push_back(MockRead(ASYNC, OK, 3));
1375 } else {
1376 data2_writes.push_back(
1377 MockWrite(ASYNC, kHttpRequest, strlen(kHttpRequest), 0));
1378
1379 data2_reads.push_back(
1380 MockRead(ASYNC, kHttpResponse, strlen(kHttpResponse), 1));
1381 data2_reads.push_back(MockRead(ASYNC, kHttpData, strlen(kHttpData), 2));
1382 data2_reads.push_back(MockRead(ASYNC, OK, 3));
1383 }
1384 OrderedSocketData data2(&data2_reads[0], data2_reads.size(),
1385 &data2_writes[0], data2_writes.size());
1386 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1387
1388 // Preconnect a socket.
1389 net::SSLConfig ssl_config;
1390 session->ssl_config_service()->GetSSLConfig(&ssl_config);
1391 session->GetNextProtos(&ssl_config.next_protos);
1392 session->http_stream_factory()->PreconnectStreams(
1393 1, request, DEFAULT_PRIORITY, ssl_config, ssl_config);
1394 // Wait for the preconnect to complete.
1395 // TODO(davidben): Some way to wait for an idle socket count might be handy.
1396 base::RunLoop().RunUntilIdle();
1397 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
1398
1399 // Make the request.
1400 TestCompletionCallback callback;
1401
1402 scoped_ptr<HttpTransaction> trans(
1403 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1404
1405 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1406 EXPECT_EQ(ERR_IO_PENDING, rv);
1407
1408 rv = callback.WaitForResult();
1409 EXPECT_EQ(OK, rv);
1410
1411 LoadTimingInfo load_timing_info;
1412 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
1413 TestLoadTimingNotReused(
1414 load_timing_info,
1415 CONNECT_TIMING_HAS_DNS_TIMES|CONNECT_TIMING_HAS_SSL_TIMES);
1416
1417 const HttpResponseInfo* response = trans->GetResponseInfo();
1418 ASSERT_TRUE(response != NULL);
1419
1420 EXPECT_TRUE(response->headers.get() != NULL);
1421 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1422
1423 std::string response_data;
1424 rv = ReadTransaction(trans.get(), &response_data);
1425 EXPECT_EQ(OK, rv);
1426 EXPECT_EQ(kHttpData, response_data);
1427 }
1428
TEST_P(HttpNetworkTransactionTest,KeepAliveConnectionNotConnectedOnWrite)1429 TEST_P(HttpNetworkTransactionTest,
1430 KeepAliveConnectionNotConnectedOnWrite) {
1431 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
1432 KeepAliveConnectionResendRequestTest(&write_failure, NULL);
1433 }
1434
TEST_P(HttpNetworkTransactionTest,KeepAliveConnectionReset)1435 TEST_P(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
1436 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
1437 KeepAliveConnectionResendRequestTest(NULL, &read_failure);
1438 }
1439
TEST_P(HttpNetworkTransactionTest,KeepAliveConnectionEOF)1440 TEST_P(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
1441 MockRead read_failure(SYNCHRONOUS, OK); // EOF
1442 KeepAliveConnectionResendRequestTest(NULL, &read_failure);
1443 }
1444
1445 // Make sure that on a 408 response (Request Timeout), the request is retried,
1446 // if the socket was a reused keep alive socket.
TEST_P(HttpNetworkTransactionTest,KeepAlive408)1447 TEST_P(HttpNetworkTransactionTest, KeepAlive408) {
1448 MockRead read_failure(SYNCHRONOUS,
1449 "HTTP/1.1 408 Request Timeout\r\n"
1450 "Connection: Keep-Alive\r\n"
1451 "Content-Length: 6\r\n\r\n"
1452 "Pickle");
1453 KeepAliveConnectionResendRequestTest(NULL, &read_failure);
1454 }
1455
TEST_P(HttpNetworkTransactionTest,PreconnectErrorNotConnectedOnWrite)1456 TEST_P(HttpNetworkTransactionTest,
1457 PreconnectErrorNotConnectedOnWrite) {
1458 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
1459 PreconnectErrorResendRequestTest(&write_failure, NULL, false);
1460 }
1461
TEST_P(HttpNetworkTransactionTest,PreconnectErrorReset)1462 TEST_P(HttpNetworkTransactionTest, PreconnectErrorReset) {
1463 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
1464 PreconnectErrorResendRequestTest(NULL, &read_failure, false);
1465 }
1466
TEST_P(HttpNetworkTransactionTest,PreconnectErrorEOF)1467 TEST_P(HttpNetworkTransactionTest, PreconnectErrorEOF) {
1468 MockRead read_failure(SYNCHRONOUS, OK); // EOF
1469 PreconnectErrorResendRequestTest(NULL, &read_failure, false);
1470 }
1471
TEST_P(HttpNetworkTransactionTest,PreconnectErrorAsyncEOF)1472 TEST_P(HttpNetworkTransactionTest, PreconnectErrorAsyncEOF) {
1473 MockRead read_failure(ASYNC, OK); // EOF
1474 PreconnectErrorResendRequestTest(NULL, &read_failure, false);
1475 }
1476
1477 // Make sure that on a 408 response (Request Timeout), the request is retried,
1478 // if the socket was a preconnected (UNUSED_IDLE) socket.
TEST_P(HttpNetworkTransactionTest,RetryOnIdle408)1479 TEST_P(HttpNetworkTransactionTest, RetryOnIdle408) {
1480 MockRead read_failure(SYNCHRONOUS,
1481 "HTTP/1.1 408 Request Timeout\r\n"
1482 "Connection: Keep-Alive\r\n"
1483 "Content-Length: 6\r\n\r\n"
1484 "Pickle");
1485 KeepAliveConnectionResendRequestTest(NULL, &read_failure);
1486 PreconnectErrorResendRequestTest(NULL, &read_failure, false);
1487 }
1488
TEST_P(HttpNetworkTransactionTest,SpdyPreconnectErrorNotConnectedOnWrite)1489 TEST_P(HttpNetworkTransactionTest,
1490 SpdyPreconnectErrorNotConnectedOnWrite) {
1491 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
1492 PreconnectErrorResendRequestTest(&write_failure, NULL, true);
1493 }
1494
TEST_P(HttpNetworkTransactionTest,SpdyPreconnectErrorReset)1495 TEST_P(HttpNetworkTransactionTest, SpdyPreconnectErrorReset) {
1496 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
1497 PreconnectErrorResendRequestTest(NULL, &read_failure, true);
1498 }
1499
TEST_P(HttpNetworkTransactionTest,SpdyPreconnectErrorEOF)1500 TEST_P(HttpNetworkTransactionTest, SpdyPreconnectErrorEOF) {
1501 MockRead read_failure(SYNCHRONOUS, OK); // EOF
1502 PreconnectErrorResendRequestTest(NULL, &read_failure, true);
1503 }
1504
TEST_P(HttpNetworkTransactionTest,SpdyPreconnectErrorAsyncEOF)1505 TEST_P(HttpNetworkTransactionTest, SpdyPreconnectErrorAsyncEOF) {
1506 MockRead read_failure(ASYNC, OK); // EOF
1507 PreconnectErrorResendRequestTest(NULL, &read_failure, true);
1508 }
1509
TEST_P(HttpNetworkTransactionTest,NonKeepAliveConnectionReset)1510 TEST_P(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
1511 HttpRequestInfo request;
1512 request.method = "GET";
1513 request.url = GURL("http://www.google.com/");
1514 request.load_flags = 0;
1515
1516 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1517 scoped_ptr<HttpTransaction> trans(
1518 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
1519
1520 MockRead data_reads[] = {
1521 MockRead(ASYNC, ERR_CONNECTION_RESET),
1522 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
1523 MockRead("hello world"),
1524 MockRead(SYNCHRONOUS, OK),
1525 };
1526 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1527 session_deps_.socket_factory->AddSocketDataProvider(&data);
1528
1529 TestCompletionCallback callback;
1530
1531 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1532 EXPECT_EQ(ERR_IO_PENDING, rv);
1533
1534 rv = callback.WaitForResult();
1535 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
1536
1537 const HttpResponseInfo* response = trans->GetResponseInfo();
1538 EXPECT_TRUE(response == NULL);
1539 }
1540
1541 // What do various browsers do when the server closes a non-keepalive
1542 // connection without sending any response header or body?
1543 //
1544 // IE7: error page
1545 // Safari 3.1.2 (Windows): error page
1546 // Firefox 3.0.1: blank page
1547 // Opera 9.52: after five attempts, blank page
1548 // Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
1549 // Us: error page (EMPTY_RESPONSE)
TEST_P(HttpNetworkTransactionTest,NonKeepAliveConnectionEOF)1550 TEST_P(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
1551 MockRead data_reads[] = {
1552 MockRead(SYNCHRONOUS, OK), // EOF
1553 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
1554 MockRead("hello world"),
1555 MockRead(SYNCHRONOUS, OK),
1556 };
1557 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
1558 arraysize(data_reads));
1559 EXPECT_EQ(ERR_EMPTY_RESPONSE, out.rv);
1560 }
1561
1562 // Test that network access can be deferred and resumed.
TEST_P(HttpNetworkTransactionTest,ThrottleBeforeNetworkStart)1563 TEST_P(HttpNetworkTransactionTest, ThrottleBeforeNetworkStart) {
1564 HttpRequestInfo request;
1565 request.method = "GET";
1566 request.url = GURL("http://www.google.com/");
1567 request.load_flags = 0;
1568
1569 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1570 scoped_ptr<HttpTransaction> trans(
1571 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1572
1573 // Defer on OnBeforeNetworkStart.
1574 BeforeNetworkStartHandler net_start_handler(true); // defer
1575 trans->SetBeforeNetworkStartCallback(
1576 base::Bind(&BeforeNetworkStartHandler::OnBeforeNetworkStart,
1577 base::Unretained(&net_start_handler)));
1578
1579 MockRead data_reads[] = {
1580 MockRead("HTTP/1.0 200 OK\r\n"),
1581 MockRead("Content-Length: 5\r\n\r\n"),
1582 MockRead("hello"),
1583 MockRead(SYNCHRONOUS, 0),
1584 };
1585 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1586 session_deps_.socket_factory->AddSocketDataProvider(&data);
1587
1588 TestCompletionCallback callback;
1589
1590 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1591 EXPECT_EQ(ERR_IO_PENDING, rv);
1592 base::MessageLoop::current()->RunUntilIdle();
1593
1594 // Should have deferred for network start.
1595 EXPECT_TRUE(net_start_handler.observed_before_network_start());
1596 EXPECT_EQ(LOAD_STATE_WAITING_FOR_DELEGATE, trans->GetLoadState());
1597 EXPECT_TRUE(trans->GetResponseInfo() == NULL);
1598
1599 trans->ResumeNetworkStart();
1600 rv = callback.WaitForResult();
1601 EXPECT_EQ(OK, rv);
1602 EXPECT_TRUE(trans->GetResponseInfo() != NULL);
1603
1604 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(100));
1605 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
1606 if (rv == ERR_IO_PENDING)
1607 rv = callback.WaitForResult();
1608 EXPECT_EQ(5, rv);
1609 trans.reset();
1610 }
1611
1612 // Test that network use can be deferred and canceled.
TEST_P(HttpNetworkTransactionTest,ThrottleAndCancelBeforeNetworkStart)1613 TEST_P(HttpNetworkTransactionTest, ThrottleAndCancelBeforeNetworkStart) {
1614 HttpRequestInfo request;
1615 request.method = "GET";
1616 request.url = GURL("http://www.google.com/");
1617 request.load_flags = 0;
1618
1619 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1620 scoped_ptr<HttpTransaction> trans(
1621 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1622
1623 // Defer on OnBeforeNetworkStart.
1624 BeforeNetworkStartHandler net_start_handler(true); // defer
1625 trans->SetBeforeNetworkStartCallback(
1626 base::Bind(&BeforeNetworkStartHandler::OnBeforeNetworkStart,
1627 base::Unretained(&net_start_handler)));
1628
1629 TestCompletionCallback callback;
1630
1631 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1632 EXPECT_EQ(ERR_IO_PENDING, rv);
1633 base::MessageLoop::current()->RunUntilIdle();
1634
1635 // Should have deferred for network start.
1636 EXPECT_TRUE(net_start_handler.observed_before_network_start());
1637 EXPECT_EQ(LOAD_STATE_WAITING_FOR_DELEGATE, trans->GetLoadState());
1638 EXPECT_TRUE(trans->GetResponseInfo() == NULL);
1639 }
1640
1641 // Next 2 cases (KeepAliveEarlyClose and KeepAliveEarlyClose2) are regression
1642 // tests. There was a bug causing HttpNetworkTransaction to hang in the
1643 // destructor in such situations.
1644 // See http://crbug.com/154712 and http://crbug.com/156609.
TEST_P(HttpNetworkTransactionTest,KeepAliveEarlyClose)1645 TEST_P(HttpNetworkTransactionTest, KeepAliveEarlyClose) {
1646 HttpRequestInfo request;
1647 request.method = "GET";
1648 request.url = GURL("http://www.google.com/");
1649 request.load_flags = 0;
1650
1651 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1652 scoped_ptr<HttpTransaction> trans(
1653 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1654
1655 MockRead data_reads[] = {
1656 MockRead("HTTP/1.0 200 OK\r\n"),
1657 MockRead("Connection: keep-alive\r\n"),
1658 MockRead("Content-Length: 100\r\n\r\n"),
1659 MockRead("hello"),
1660 MockRead(SYNCHRONOUS, 0),
1661 };
1662 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1663 session_deps_.socket_factory->AddSocketDataProvider(&data);
1664
1665 TestCompletionCallback callback;
1666
1667 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1668 EXPECT_EQ(ERR_IO_PENDING, rv);
1669
1670 rv = callback.WaitForResult();
1671 EXPECT_EQ(OK, rv);
1672
1673 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(100));
1674 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
1675 if (rv == ERR_IO_PENDING)
1676 rv = callback.WaitForResult();
1677 EXPECT_EQ(5, rv);
1678 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
1679 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH, rv);
1680
1681 trans.reset();
1682 base::MessageLoop::current()->RunUntilIdle();
1683 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
1684 }
1685
TEST_P(HttpNetworkTransactionTest,KeepAliveEarlyClose2)1686 TEST_P(HttpNetworkTransactionTest, KeepAliveEarlyClose2) {
1687 HttpRequestInfo request;
1688 request.method = "GET";
1689 request.url = GURL("http://www.google.com/");
1690 request.load_flags = 0;
1691
1692 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1693 scoped_ptr<HttpTransaction> trans(
1694 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1695
1696 MockRead data_reads[] = {
1697 MockRead("HTTP/1.0 200 OK\r\n"),
1698 MockRead("Connection: keep-alive\r\n"),
1699 MockRead("Content-Length: 100\r\n\r\n"),
1700 MockRead(SYNCHRONOUS, 0),
1701 };
1702 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1703 session_deps_.socket_factory->AddSocketDataProvider(&data);
1704
1705 TestCompletionCallback callback;
1706
1707 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1708 EXPECT_EQ(ERR_IO_PENDING, rv);
1709
1710 rv = callback.WaitForResult();
1711 EXPECT_EQ(OK, rv);
1712
1713 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(100));
1714 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
1715 if (rv == ERR_IO_PENDING)
1716 rv = callback.WaitForResult();
1717 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH, rv);
1718
1719 trans.reset();
1720 base::MessageLoop::current()->RunUntilIdle();
1721 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
1722 }
1723
1724 // Test that we correctly reuse a keep-alive connection after not explicitly
1725 // reading the body.
TEST_P(HttpNetworkTransactionTest,KeepAliveAfterUnreadBody)1726 TEST_P(HttpNetworkTransactionTest, KeepAliveAfterUnreadBody) {
1727 HttpRequestInfo request;
1728 request.method = "GET";
1729 request.url = GURL("http://www.foo.com/");
1730 request.load_flags = 0;
1731
1732 CapturingNetLog net_log;
1733 session_deps_.net_log = &net_log;
1734 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1735
1736 // Note that because all these reads happen in the same
1737 // StaticSocketDataProvider, it shows that the same socket is being reused for
1738 // all transactions.
1739 MockRead data1_reads[] = {
1740 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
1741 MockRead("HTTP/1.1 205 Reset Content\r\n\r\n"),
1742 MockRead("HTTP/1.1 304 Not Modified\r\n\r\n"),
1743 MockRead("HTTP/1.1 302 Found\r\n"
1744 "Content-Length: 0\r\n\r\n"),
1745 MockRead("HTTP/1.1 302 Found\r\n"
1746 "Content-Length: 5\r\n\r\n"
1747 "hello"),
1748 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
1749 "Content-Length: 0\r\n\r\n"),
1750 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
1751 "Content-Length: 5\r\n\r\n"
1752 "hello"),
1753 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1754 MockRead("hello"),
1755 };
1756 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), NULL, 0);
1757 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1758
1759 MockRead data2_reads[] = {
1760 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
1761 };
1762 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
1763 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1764
1765 const int kNumUnreadBodies = arraysize(data1_reads) - 2;
1766 std::string response_lines[kNumUnreadBodies];
1767
1768 uint32 first_socket_log_id = NetLog::Source::kInvalidId;
1769 for (size_t i = 0; i < arraysize(data1_reads) - 2; ++i) {
1770 TestCompletionCallback callback;
1771
1772 scoped_ptr<HttpTransaction> trans(
1773 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1774
1775 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1776 EXPECT_EQ(ERR_IO_PENDING, rv);
1777
1778 rv = callback.WaitForResult();
1779 EXPECT_EQ(OK, rv);
1780
1781 LoadTimingInfo load_timing_info;
1782 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
1783 if (i == 0) {
1784 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
1785 first_socket_log_id = load_timing_info.socket_log_id;
1786 } else {
1787 TestLoadTimingReused(load_timing_info);
1788 EXPECT_EQ(first_socket_log_id, load_timing_info.socket_log_id);
1789 }
1790
1791 const HttpResponseInfo* response = trans->GetResponseInfo();
1792 ASSERT_TRUE(response != NULL);
1793
1794 ASSERT_TRUE(response->headers.get() != NULL);
1795 response_lines[i] = response->headers->GetStatusLine();
1796
1797 // We intentionally don't read the response bodies.
1798 }
1799
1800 const char* const kStatusLines[] = {
1801 "HTTP/1.1 204 No Content",
1802 "HTTP/1.1 205 Reset Content",
1803 "HTTP/1.1 304 Not Modified",
1804 "HTTP/1.1 302 Found",
1805 "HTTP/1.1 302 Found",
1806 "HTTP/1.1 301 Moved Permanently",
1807 "HTTP/1.1 301 Moved Permanently",
1808 };
1809
1810 COMPILE_ASSERT(kNumUnreadBodies == arraysize(kStatusLines),
1811 forgot_to_update_kStatusLines);
1812
1813 for (int i = 0; i < kNumUnreadBodies; ++i)
1814 EXPECT_EQ(kStatusLines[i], response_lines[i]);
1815
1816 TestCompletionCallback callback;
1817 scoped_ptr<HttpTransaction> trans(
1818 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1819 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1820 EXPECT_EQ(ERR_IO_PENDING, rv);
1821 rv = callback.WaitForResult();
1822 EXPECT_EQ(OK, rv);
1823 const HttpResponseInfo* response = trans->GetResponseInfo();
1824 ASSERT_TRUE(response != NULL);
1825 ASSERT_TRUE(response->headers.get() != NULL);
1826 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1827 std::string response_data;
1828 rv = ReadTransaction(trans.get(), &response_data);
1829 EXPECT_EQ(OK, rv);
1830 EXPECT_EQ("hello", response_data);
1831 }
1832
1833 // Test the request-challenge-retry sequence for basic auth.
1834 // (basic auth is the easiest to mock, because it has no randomness).
TEST_P(HttpNetworkTransactionTest,BasicAuth)1835 TEST_P(HttpNetworkTransactionTest, BasicAuth) {
1836 HttpRequestInfo request;
1837 request.method = "GET";
1838 request.url = GURL("http://www.google.com/");
1839 request.load_flags = 0;
1840
1841 CapturingNetLog log;
1842 session_deps_.net_log = &log;
1843 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1844 scoped_ptr<HttpTransaction> trans(
1845 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
1846
1847 MockWrite data_writes1[] = {
1848 MockWrite("GET / HTTP/1.1\r\n"
1849 "Host: www.google.com\r\n"
1850 "Connection: keep-alive\r\n\r\n"),
1851 };
1852
1853 MockRead data_reads1[] = {
1854 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1855 // Give a couple authenticate options (only the middle one is actually
1856 // supported).
1857 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
1858 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1859 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
1860 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1861 // Large content-length -- won't matter, as connection will be reset.
1862 MockRead("Content-Length: 10000\r\n\r\n"),
1863 MockRead(SYNCHRONOUS, ERR_FAILED),
1864 };
1865
1866 // After calling trans->RestartWithAuth(), this is the request we should
1867 // be issuing -- the final header line contains the credentials.
1868 MockWrite data_writes2[] = {
1869 MockWrite("GET / HTTP/1.1\r\n"
1870 "Host: www.google.com\r\n"
1871 "Connection: keep-alive\r\n"
1872 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1873 };
1874
1875 // Lastly, the server responds with the actual content.
1876 MockRead data_reads2[] = {
1877 MockRead("HTTP/1.0 200 OK\r\n"),
1878 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1879 MockRead("Content-Length: 100\r\n\r\n"),
1880 MockRead(SYNCHRONOUS, OK),
1881 };
1882
1883 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1884 data_writes1, arraysize(data_writes1));
1885 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1886 data_writes2, arraysize(data_writes2));
1887 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1888 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1889
1890 TestCompletionCallback callback1;
1891
1892 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
1893 EXPECT_EQ(ERR_IO_PENDING, rv);
1894
1895 rv = callback1.WaitForResult();
1896 EXPECT_EQ(OK, rv);
1897
1898 LoadTimingInfo load_timing_info1;
1899 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info1));
1900 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
1901
1902 int64 reads_size1 = ReadsSize(data_reads1, arraysize(data_reads1));
1903 EXPECT_EQ(reads_size1, trans->GetTotalReceivedBytes());
1904
1905 const HttpResponseInfo* response = trans->GetResponseInfo();
1906 ASSERT_TRUE(response != NULL);
1907 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
1908
1909 TestCompletionCallback callback2;
1910
1911 rv = trans->RestartWithAuth(
1912 AuthCredentials(kFoo, kBar), callback2.callback());
1913 EXPECT_EQ(ERR_IO_PENDING, rv);
1914
1915 rv = callback2.WaitForResult();
1916 EXPECT_EQ(OK, rv);
1917
1918 LoadTimingInfo load_timing_info2;
1919 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info2));
1920 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_DNS_TIMES);
1921 // The load timing after restart should have a new socket ID, and times after
1922 // those of the first load timing.
1923 EXPECT_LE(load_timing_info1.receive_headers_end,
1924 load_timing_info2.connect_timing.connect_start);
1925 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
1926
1927 int64 reads_size2 = ReadsSize(data_reads2, arraysize(data_reads2));
1928 EXPECT_EQ(reads_size1 + reads_size2, trans->GetTotalReceivedBytes());
1929
1930 response = trans->GetResponseInfo();
1931 ASSERT_TRUE(response != NULL);
1932 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1933 EXPECT_EQ(100, response->headers->GetContentLength());
1934 }
1935
TEST_P(HttpNetworkTransactionTest,DoNotSendAuth)1936 TEST_P(HttpNetworkTransactionTest, DoNotSendAuth) {
1937 HttpRequestInfo request;
1938 request.method = "GET";
1939 request.url = GURL("http://www.google.com/");
1940 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
1941
1942 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1943 scoped_ptr<HttpTransaction> trans(
1944 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
1945
1946 MockWrite data_writes[] = {
1947 MockWrite("GET / HTTP/1.1\r\n"
1948 "Host: www.google.com\r\n"
1949 "Connection: keep-alive\r\n\r\n"),
1950 };
1951
1952 MockRead data_reads[] = {
1953 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1954 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1955 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1956 // Large content-length -- won't matter, as connection will be reset.
1957 MockRead("Content-Length: 10000\r\n\r\n"),
1958 MockRead(SYNCHRONOUS, ERR_FAILED),
1959 };
1960
1961 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1962 data_writes, arraysize(data_writes));
1963 session_deps_.socket_factory->AddSocketDataProvider(&data);
1964 TestCompletionCallback callback;
1965
1966 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1967 EXPECT_EQ(ERR_IO_PENDING, rv);
1968
1969 rv = callback.WaitForResult();
1970 EXPECT_EQ(0, rv);
1971
1972 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
1973 EXPECT_EQ(reads_size, trans->GetTotalReceivedBytes());
1974
1975 const HttpResponseInfo* response = trans->GetResponseInfo();
1976 ASSERT_TRUE(response != NULL);
1977 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1978 }
1979
1980 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
1981 // connection.
TEST_P(HttpNetworkTransactionTest,BasicAuthKeepAlive)1982 TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
1983 HttpRequestInfo request;
1984 request.method = "GET";
1985 request.url = GURL("http://www.google.com/");
1986 request.load_flags = 0;
1987
1988 CapturingNetLog log;
1989 session_deps_.net_log = &log;
1990 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1991
1992 MockWrite data_writes1[] = {
1993 MockWrite("GET / HTTP/1.1\r\n"
1994 "Host: www.google.com\r\n"
1995 "Connection: keep-alive\r\n\r\n"),
1996
1997 // After calling trans->RestartWithAuth(), this is the request we should
1998 // be issuing -- the final header line contains the credentials.
1999 MockWrite("GET / HTTP/1.1\r\n"
2000 "Host: www.google.com\r\n"
2001 "Connection: keep-alive\r\n"
2002 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2003 };
2004
2005 MockRead data_reads1[] = {
2006 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2007 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2008 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2009 MockRead("Content-Length: 14\r\n\r\n"),
2010 MockRead("Unauthorized\r\n"),
2011
2012 // Lastly, the server responds with the actual content.
2013 MockRead("HTTP/1.1 200 OK\r\n"),
2014 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2015 MockRead("Content-Length: 5\r\n\r\n"),
2016 MockRead("Hello"),
2017 };
2018
2019 // If there is a regression where we disconnect a Keep-Alive
2020 // connection during an auth roundtrip, we'll end up reading this.
2021 MockRead data_reads2[] = {
2022 MockRead(SYNCHRONOUS, ERR_FAILED),
2023 };
2024
2025 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2026 data_writes1, arraysize(data_writes1));
2027 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2028 NULL, 0);
2029 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2030 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2031
2032 TestCompletionCallback callback1;
2033
2034 scoped_ptr<HttpTransaction> trans(
2035 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2036 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
2037 EXPECT_EQ(ERR_IO_PENDING, rv);
2038
2039 rv = callback1.WaitForResult();
2040 EXPECT_EQ(OK, rv);
2041
2042 LoadTimingInfo load_timing_info1;
2043 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info1));
2044 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
2045
2046 const HttpResponseInfo* response = trans->GetResponseInfo();
2047 ASSERT_TRUE(response != NULL);
2048 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
2049
2050 TestCompletionCallback callback2;
2051
2052 rv = trans->RestartWithAuth(
2053 AuthCredentials(kFoo, kBar), callback2.callback());
2054 EXPECT_EQ(ERR_IO_PENDING, rv);
2055
2056 rv = callback2.WaitForResult();
2057 EXPECT_EQ(OK, rv);
2058
2059 LoadTimingInfo load_timing_info2;
2060 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info2));
2061 TestLoadTimingReused(load_timing_info2);
2062 // The load timing after restart should have the same socket ID, and times
2063 // those of the first load timing.
2064 EXPECT_LE(load_timing_info1.receive_headers_end,
2065 load_timing_info2.send_start);
2066 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
2067
2068 response = trans->GetResponseInfo();
2069 ASSERT_TRUE(response != NULL);
2070 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2071 EXPECT_EQ(5, response->headers->GetContentLength());
2072
2073 std::string response_data;
2074 rv = ReadTransaction(trans.get(), &response_data);
2075 EXPECT_EQ(OK, rv);
2076 int64 reads_size1 = ReadsSize(data_reads1, arraysize(data_reads1));
2077 EXPECT_EQ(reads_size1, trans->GetTotalReceivedBytes());
2078 }
2079
2080 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2081 // connection and with no response body to drain.
TEST_P(HttpNetworkTransactionTest,BasicAuthKeepAliveNoBody)2082 TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
2083 HttpRequestInfo request;
2084 request.method = "GET";
2085 request.url = GURL("http://www.google.com/");
2086 request.load_flags = 0;
2087
2088 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2089
2090 MockWrite data_writes1[] = {
2091 MockWrite("GET / HTTP/1.1\r\n"
2092 "Host: www.google.com\r\n"
2093 "Connection: keep-alive\r\n\r\n"),
2094
2095 // After calling trans->RestartWithAuth(), this is the request we should
2096 // be issuing -- the final header line contains the credentials.
2097 MockWrite("GET / HTTP/1.1\r\n"
2098 "Host: www.google.com\r\n"
2099 "Connection: keep-alive\r\n"
2100 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2101 };
2102
2103 MockRead data_reads1[] = {
2104 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2105 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2106 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
2107
2108 // Lastly, the server responds with the actual content.
2109 MockRead("HTTP/1.1 200 OK\r\n"),
2110 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2111 MockRead("Content-Length: 5\r\n\r\n"),
2112 MockRead("hello"),
2113 };
2114
2115 // An incorrect reconnect would cause this to be read.
2116 MockRead data_reads2[] = {
2117 MockRead(SYNCHRONOUS, ERR_FAILED),
2118 };
2119
2120 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2121 data_writes1, arraysize(data_writes1));
2122 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2123 NULL, 0);
2124 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2125 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2126
2127 TestCompletionCallback callback1;
2128
2129 scoped_ptr<HttpTransaction> trans(
2130 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2131 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
2132 EXPECT_EQ(ERR_IO_PENDING, rv);
2133
2134 rv = callback1.WaitForResult();
2135 EXPECT_EQ(OK, rv);
2136
2137 const HttpResponseInfo* response = trans->GetResponseInfo();
2138 ASSERT_TRUE(response != NULL);
2139 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
2140
2141 TestCompletionCallback callback2;
2142
2143 rv = trans->RestartWithAuth(
2144 AuthCredentials(kFoo, kBar), callback2.callback());
2145 EXPECT_EQ(ERR_IO_PENDING, rv);
2146
2147 rv = callback2.WaitForResult();
2148 EXPECT_EQ(OK, rv);
2149
2150 response = trans->GetResponseInfo();
2151 ASSERT_TRUE(response != NULL);
2152 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2153 EXPECT_EQ(5, response->headers->GetContentLength());
2154 }
2155
2156 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2157 // connection and with a large response body to drain.
TEST_P(HttpNetworkTransactionTest,BasicAuthKeepAliveLargeBody)2158 TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
2159 HttpRequestInfo request;
2160 request.method = "GET";
2161 request.url = GURL("http://www.google.com/");
2162 request.load_flags = 0;
2163
2164 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2165
2166 MockWrite data_writes1[] = {
2167 MockWrite("GET / HTTP/1.1\r\n"
2168 "Host: www.google.com\r\n"
2169 "Connection: keep-alive\r\n\r\n"),
2170
2171 // After calling trans->RestartWithAuth(), this is the request we should
2172 // be issuing -- the final header line contains the credentials.
2173 MockWrite("GET / HTTP/1.1\r\n"
2174 "Host: www.google.com\r\n"
2175 "Connection: keep-alive\r\n"
2176 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2177 };
2178
2179 // Respond with 5 kb of response body.
2180 std::string large_body_string("Unauthorized");
2181 large_body_string.append(5 * 1024, ' ');
2182 large_body_string.append("\r\n");
2183
2184 MockRead data_reads1[] = {
2185 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2186 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2187 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2188 // 5134 = 12 + 5 * 1024 + 2
2189 MockRead("Content-Length: 5134\r\n\r\n"),
2190 MockRead(ASYNC, large_body_string.data(), large_body_string.size()),
2191
2192 // Lastly, the server responds with the actual content.
2193 MockRead("HTTP/1.1 200 OK\r\n"),
2194 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2195 MockRead("Content-Length: 5\r\n\r\n"),
2196 MockRead("hello"),
2197 };
2198
2199 // An incorrect reconnect would cause this to be read.
2200 MockRead data_reads2[] = {
2201 MockRead(SYNCHRONOUS, ERR_FAILED),
2202 };
2203
2204 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2205 data_writes1, arraysize(data_writes1));
2206 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2207 NULL, 0);
2208 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2209 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2210
2211 TestCompletionCallback callback1;
2212
2213 scoped_ptr<HttpTransaction> trans(
2214 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2215 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
2216 EXPECT_EQ(ERR_IO_PENDING, rv);
2217
2218 rv = callback1.WaitForResult();
2219 EXPECT_EQ(OK, rv);
2220
2221 const HttpResponseInfo* response = trans->GetResponseInfo();
2222 ASSERT_TRUE(response != NULL);
2223 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
2224
2225 TestCompletionCallback callback2;
2226
2227 rv = trans->RestartWithAuth(
2228 AuthCredentials(kFoo, kBar), callback2.callback());
2229 EXPECT_EQ(ERR_IO_PENDING, rv);
2230
2231 rv = callback2.WaitForResult();
2232 EXPECT_EQ(OK, rv);
2233
2234 response = trans->GetResponseInfo();
2235 ASSERT_TRUE(response != NULL);
2236 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2237 EXPECT_EQ(5, response->headers->GetContentLength());
2238 }
2239
2240 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2241 // connection, but the server gets impatient and closes the connection.
TEST_P(HttpNetworkTransactionTest,BasicAuthKeepAliveImpatientServer)2242 TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) {
2243 HttpRequestInfo request;
2244 request.method = "GET";
2245 request.url = GURL("http://www.google.com/");
2246 request.load_flags = 0;
2247
2248 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2249
2250 MockWrite data_writes1[] = {
2251 MockWrite("GET / HTTP/1.1\r\n"
2252 "Host: www.google.com\r\n"
2253 "Connection: keep-alive\r\n\r\n"),
2254 // This simulates the seemingly successful write to a closed connection
2255 // if the bug is not fixed.
2256 MockWrite("GET / HTTP/1.1\r\n"
2257 "Host: www.google.com\r\n"
2258 "Connection: keep-alive\r\n"
2259 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2260 };
2261
2262 MockRead data_reads1[] = {
2263 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2264 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2265 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2266 MockRead("Content-Length: 14\r\n\r\n"),
2267 // Tell MockTCPClientSocket to simulate the server closing the connection.
2268 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
2269 MockRead("Unauthorized\r\n"),
2270 MockRead(SYNCHRONOUS, OK), // The server closes the connection.
2271 };
2272
2273 // After calling trans->RestartWithAuth(), this is the request we should
2274 // be issuing -- the final header line contains the credentials.
2275 MockWrite data_writes2[] = {
2276 MockWrite("GET / HTTP/1.1\r\n"
2277 "Host: www.google.com\r\n"
2278 "Connection: keep-alive\r\n"
2279 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2280 };
2281
2282 // Lastly, the server responds with the actual content.
2283 MockRead data_reads2[] = {
2284 MockRead("HTTP/1.1 200 OK\r\n"),
2285 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2286 MockRead("Content-Length: 5\r\n\r\n"),
2287 MockRead("hello"),
2288 };
2289
2290 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2291 data_writes1, arraysize(data_writes1));
2292 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2293 data_writes2, arraysize(data_writes2));
2294 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2295 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2296
2297 TestCompletionCallback callback1;
2298
2299 scoped_ptr<HttpTransaction> trans(
2300 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2301 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
2302 EXPECT_EQ(ERR_IO_PENDING, rv);
2303
2304 rv = callback1.WaitForResult();
2305 EXPECT_EQ(OK, rv);
2306
2307 const HttpResponseInfo* response = trans->GetResponseInfo();
2308 ASSERT_TRUE(response != NULL);
2309 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
2310
2311 TestCompletionCallback callback2;
2312
2313 rv = trans->RestartWithAuth(
2314 AuthCredentials(kFoo, kBar), callback2.callback());
2315 EXPECT_EQ(ERR_IO_PENDING, rv);
2316
2317 rv = callback2.WaitForResult();
2318 EXPECT_EQ(OK, rv);
2319
2320 response = trans->GetResponseInfo();
2321 ASSERT_TRUE(response != NULL);
2322 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2323 EXPECT_EQ(5, response->headers->GetContentLength());
2324 }
2325
2326 // Test the request-challenge-retry sequence for basic auth, over a connection
2327 // that requires a restart when setting up an SSL tunnel.
TEST_P(HttpNetworkTransactionTest,BasicAuthProxyNoKeepAlive)2328 TEST_P(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAlive) {
2329 HttpRequestInfo request;
2330 request.method = "GET";
2331 request.url = GURL("https://www.google.com/");
2332 // when the no authentication data flag is set.
2333 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
2334
2335 // Configure against proxy server "myproxy:70".
2336 session_deps_.proxy_service.reset(
2337 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
2338 CapturingBoundNetLog log;
2339 session_deps_.net_log = log.bound().net_log();
2340 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2341
2342 // Since we have proxy, should try to establish tunnel.
2343 MockWrite data_writes1[] = {
2344 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2345 "Host: www.google.com\r\n"
2346 "Proxy-Connection: keep-alive\r\n\r\n"),
2347
2348 // After calling trans->RestartWithAuth(), this is the request we should
2349 // be issuing -- the final header line contains the credentials.
2350 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2351 "Host: www.google.com\r\n"
2352 "Proxy-Connection: keep-alive\r\n"
2353 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2354
2355 MockWrite("GET / HTTP/1.1\r\n"
2356 "Host: www.google.com\r\n"
2357 "Connection: keep-alive\r\n\r\n"),
2358 };
2359
2360 // The proxy responds to the connect with a 407, using a persistent
2361 // connection.
2362 MockRead data_reads1[] = {
2363 // No credentials.
2364 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2365 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2366 MockRead("Proxy-Connection: close\r\n\r\n"),
2367
2368 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2369
2370 MockRead("HTTP/1.1 200 OK\r\n"),
2371 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2372 MockRead("Content-Length: 5\r\n\r\n"),
2373 MockRead(SYNCHRONOUS, "hello"),
2374 };
2375
2376 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2377 data_writes1, arraysize(data_writes1));
2378 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2379 SSLSocketDataProvider ssl(ASYNC, OK);
2380 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2381
2382 TestCompletionCallback callback1;
2383
2384 scoped_ptr<HttpTransaction> trans(
2385 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2386
2387 int rv = trans->Start(&request, callback1.callback(), log.bound());
2388 EXPECT_EQ(ERR_IO_PENDING, rv);
2389
2390 rv = callback1.WaitForResult();
2391 EXPECT_EQ(OK, rv);
2392 net::CapturingNetLog::CapturedEntryList entries;
2393 log.GetEntries(&entries);
2394 size_t pos = ExpectLogContainsSomewhere(
2395 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
2396 NetLog::PHASE_NONE);
2397 ExpectLogContainsSomewhere(
2398 entries, pos,
2399 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
2400 NetLog::PHASE_NONE);
2401
2402 const HttpResponseInfo* response = trans->GetResponseInfo();
2403 ASSERT_TRUE(response != NULL);
2404 ASSERT_FALSE(response->headers.get() == NULL);
2405 EXPECT_EQ(407, response->headers->response_code());
2406 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2407 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2408
2409 LoadTimingInfo load_timing_info;
2410 // CONNECT requests and responses are handled at the connect job level, so
2411 // the transaction does not yet have a connection.
2412 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
2413
2414 TestCompletionCallback callback2;
2415
2416 rv = trans->RestartWithAuth(
2417 AuthCredentials(kFoo, kBar), callback2.callback());
2418 EXPECT_EQ(ERR_IO_PENDING, rv);
2419
2420 rv = callback2.WaitForResult();
2421 EXPECT_EQ(OK, rv);
2422
2423 response = trans->GetResponseInfo();
2424 ASSERT_TRUE(response != NULL);
2425
2426 EXPECT_TRUE(response->headers->IsKeepAlive());
2427 EXPECT_EQ(200, response->headers->response_code());
2428 EXPECT_EQ(5, response->headers->GetContentLength());
2429 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2430
2431 // The password prompt info should not be set.
2432 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2433
2434 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
2435 TestLoadTimingNotReusedWithPac(load_timing_info,
2436 CONNECT_TIMING_HAS_SSL_TIMES);
2437
2438 trans.reset();
2439 session->CloseAllConnections();
2440 }
2441
2442 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2443 // proxy connection, when setting up an SSL tunnel.
TEST_P(HttpNetworkTransactionTest,BasicAuthProxyKeepAlive)2444 TEST_P(HttpNetworkTransactionTest, BasicAuthProxyKeepAlive) {
2445 HttpRequestInfo request;
2446 request.method = "GET";
2447 request.url = GURL("https://www.google.com/");
2448 // Ensure that proxy authentication is attempted even
2449 // when the no authentication data flag is set.
2450 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
2451
2452 // Configure against proxy server "myproxy:70".
2453 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
2454 CapturingBoundNetLog log;
2455 session_deps_.net_log = log.bound().net_log();
2456 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2457
2458 scoped_ptr<HttpTransaction> trans(
2459 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2460
2461 // Since we have proxy, should try to establish tunnel.
2462 MockWrite data_writes1[] = {
2463 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2464 "Host: www.google.com\r\n"
2465 "Proxy-Connection: keep-alive\r\n\r\n"),
2466
2467 // After calling trans->RestartWithAuth(), this is the request we should
2468 // be issuing -- the final header line contains the credentials.
2469 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2470 "Host: www.google.com\r\n"
2471 "Proxy-Connection: keep-alive\r\n"
2472 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
2473 };
2474
2475 // The proxy responds to the connect with a 407, using a persistent
2476 // connection.
2477 MockRead data_reads1[] = {
2478 // No credentials.
2479 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2480 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2481 MockRead("Content-Length: 10\r\n\r\n"),
2482 MockRead("0123456789"),
2483
2484 // Wrong credentials (wrong password).
2485 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2486 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2487 MockRead("Content-Length: 10\r\n\r\n"),
2488 // No response body because the test stops reading here.
2489 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
2490 };
2491
2492 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2493 data_writes1, arraysize(data_writes1));
2494 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2495
2496 TestCompletionCallback callback1;
2497
2498 int rv = trans->Start(&request, callback1.callback(), log.bound());
2499 EXPECT_EQ(ERR_IO_PENDING, rv);
2500
2501 rv = callback1.WaitForResult();
2502 EXPECT_EQ(OK, rv);
2503 net::CapturingNetLog::CapturedEntryList entries;
2504 log.GetEntries(&entries);
2505 size_t pos = ExpectLogContainsSomewhere(
2506 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
2507 NetLog::PHASE_NONE);
2508 ExpectLogContainsSomewhere(
2509 entries, pos,
2510 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
2511 NetLog::PHASE_NONE);
2512
2513 const HttpResponseInfo* response = trans->GetResponseInfo();
2514 ASSERT_TRUE(response != NULL);
2515 ASSERT_FALSE(response->headers.get() == NULL);
2516 EXPECT_TRUE(response->headers->IsKeepAlive());
2517 EXPECT_EQ(407, response->headers->response_code());
2518 EXPECT_EQ(10, response->headers->GetContentLength());
2519 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2520 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2521
2522 TestCompletionCallback callback2;
2523
2524 // Wrong password (should be "bar").
2525 rv = trans->RestartWithAuth(
2526 AuthCredentials(kFoo, kBaz), callback2.callback());
2527 EXPECT_EQ(ERR_IO_PENDING, rv);
2528
2529 rv = callback2.WaitForResult();
2530 EXPECT_EQ(OK, rv);
2531
2532 response = trans->GetResponseInfo();
2533 ASSERT_TRUE(response != NULL);
2534 ASSERT_FALSE(response->headers.get() == NULL);
2535 EXPECT_TRUE(response->headers->IsKeepAlive());
2536 EXPECT_EQ(407, response->headers->response_code());
2537 EXPECT_EQ(10, response->headers->GetContentLength());
2538 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2539 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2540
2541 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
2542 // out of scope.
2543 session->CloseAllConnections();
2544 }
2545
2546 // Test that we don't read the response body when we fail to establish a tunnel,
2547 // even if the user cancels the proxy's auth attempt.
TEST_P(HttpNetworkTransactionTest,BasicAuthProxyCancelTunnel)2548 TEST_P(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
2549 HttpRequestInfo request;
2550 request.method = "GET";
2551 request.url = GURL("https://www.google.com/");
2552 request.load_flags = 0;
2553
2554 // Configure against proxy server "myproxy:70".
2555 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
2556
2557 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2558
2559 scoped_ptr<HttpTransaction> trans(
2560 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2561
2562 // Since we have proxy, should try to establish tunnel.
2563 MockWrite data_writes[] = {
2564 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2565 "Host: www.google.com\r\n"
2566 "Proxy-Connection: keep-alive\r\n\r\n"),
2567 };
2568
2569 // The proxy responds to the connect with a 407.
2570 MockRead data_reads[] = {
2571 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2572 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2573 MockRead("Content-Length: 10\r\n\r\n"),
2574 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
2575 };
2576
2577 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
2578 data_writes, arraysize(data_writes));
2579 session_deps_.socket_factory->AddSocketDataProvider(&data);
2580
2581 TestCompletionCallback callback;
2582
2583 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
2584 EXPECT_EQ(ERR_IO_PENDING, rv);
2585
2586 rv = callback.WaitForResult();
2587 EXPECT_EQ(OK, rv);
2588
2589 const HttpResponseInfo* response = trans->GetResponseInfo();
2590 ASSERT_TRUE(response != NULL);
2591
2592 EXPECT_TRUE(response->headers->IsKeepAlive());
2593 EXPECT_EQ(407, response->headers->response_code());
2594 EXPECT_EQ(10, response->headers->GetContentLength());
2595 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2596
2597 std::string response_data;
2598 rv = ReadTransaction(trans.get(), &response_data);
2599 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
2600
2601 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
2602 session->CloseAllConnections();
2603 }
2604
2605 // Test when a server (non-proxy) returns a 407 (proxy-authenticate).
2606 // The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
TEST_P(HttpNetworkTransactionTest,UnexpectedProxyAuth)2607 TEST_P(HttpNetworkTransactionTest, UnexpectedProxyAuth) {
2608 HttpRequestInfo request;
2609 request.method = "GET";
2610 request.url = GURL("http://www.google.com/");
2611 request.load_flags = 0;
2612
2613 // We are using a DIRECT connection (i.e. no proxy) for this session.
2614 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2615 scoped_ptr<HttpTransaction> trans(
2616 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
2617
2618 MockWrite data_writes1[] = {
2619 MockWrite("GET / HTTP/1.1\r\n"
2620 "Host: www.google.com\r\n"
2621 "Connection: keep-alive\r\n\r\n"),
2622 };
2623
2624 MockRead data_reads1[] = {
2625 MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
2626 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2627 // Large content-length -- won't matter, as connection will be reset.
2628 MockRead("Content-Length: 10000\r\n\r\n"),
2629 MockRead(SYNCHRONOUS, ERR_FAILED),
2630 };
2631
2632 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2633 data_writes1, arraysize(data_writes1));
2634 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2635
2636 TestCompletionCallback callback;
2637
2638 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
2639 EXPECT_EQ(ERR_IO_PENDING, rv);
2640
2641 rv = callback.WaitForResult();
2642 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
2643 }
2644
2645 // Tests when an HTTPS server (non-proxy) returns a 407 (proxy-authentication)
2646 // through a non-authenticating proxy. The request should fail with
2647 // ERR_UNEXPECTED_PROXY_AUTH.
2648 // Note that it is impossible to detect if an HTTP server returns a 407 through
2649 // a non-authenticating proxy - there is nothing to indicate whether the
2650 // response came from the proxy or the server, so it is treated as if the proxy
2651 // issued the challenge.
TEST_P(HttpNetworkTransactionTest,HttpsServerRequestsProxyAuthThroughProxy)2652 TEST_P(HttpNetworkTransactionTest,
2653 HttpsServerRequestsProxyAuthThroughProxy) {
2654 HttpRequestInfo request;
2655 request.method = "GET";
2656 request.url = GURL("https://www.google.com/");
2657
2658 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
2659 CapturingBoundNetLog log;
2660 session_deps_.net_log = log.bound().net_log();
2661 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2662
2663 // Since we have proxy, should try to establish tunnel.
2664 MockWrite data_writes1[] = {
2665 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2666 "Host: www.google.com\r\n"
2667 "Proxy-Connection: keep-alive\r\n\r\n"),
2668
2669 MockWrite("GET / HTTP/1.1\r\n"
2670 "Host: www.google.com\r\n"
2671 "Connection: keep-alive\r\n\r\n"),
2672 };
2673
2674 MockRead data_reads1[] = {
2675 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2676
2677 MockRead("HTTP/1.1 407 Unauthorized\r\n"),
2678 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2679 MockRead("\r\n"),
2680 MockRead(SYNCHRONOUS, OK),
2681 };
2682
2683 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2684 data_writes1, arraysize(data_writes1));
2685 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2686 SSLSocketDataProvider ssl(ASYNC, OK);
2687 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2688
2689 TestCompletionCallback callback1;
2690
2691 scoped_ptr<HttpTransaction> trans(
2692 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2693
2694 int rv = trans->Start(&request, callback1.callback(), log.bound());
2695 EXPECT_EQ(ERR_IO_PENDING, rv);
2696
2697 rv = callback1.WaitForResult();
2698 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
2699 net::CapturingNetLog::CapturedEntryList entries;
2700 log.GetEntries(&entries);
2701 size_t pos = ExpectLogContainsSomewhere(
2702 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
2703 NetLog::PHASE_NONE);
2704 ExpectLogContainsSomewhere(
2705 entries, pos,
2706 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
2707 NetLog::PHASE_NONE);
2708 }
2709
2710 // Test the load timing for HTTPS requests with an HTTP proxy.
TEST_P(HttpNetworkTransactionTest,HttpProxyLoadTimingNoPacTwoRequests)2711 TEST_P(HttpNetworkTransactionTest, HttpProxyLoadTimingNoPacTwoRequests) {
2712 HttpRequestInfo request1;
2713 request1.method = "GET";
2714 request1.url = GURL("https://www.google.com/1");
2715
2716 HttpRequestInfo request2;
2717 request2.method = "GET";
2718 request2.url = GURL("https://www.google.com/2");
2719
2720 // Configure against proxy server "myproxy:70".
2721 session_deps_.proxy_service.reset(
2722 ProxyService::CreateFixed("PROXY myproxy:70"));
2723 CapturingBoundNetLog log;
2724 session_deps_.net_log = log.bound().net_log();
2725 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2726
2727 // Since we have proxy, should try to establish tunnel.
2728 MockWrite data_writes1[] = {
2729 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2730 "Host: www.google.com\r\n"
2731 "Proxy-Connection: keep-alive\r\n\r\n"),
2732
2733 MockWrite("GET /1 HTTP/1.1\r\n"
2734 "Host: www.google.com\r\n"
2735 "Connection: keep-alive\r\n\r\n"),
2736
2737 MockWrite("GET /2 HTTP/1.1\r\n"
2738 "Host: www.google.com\r\n"
2739 "Connection: keep-alive\r\n\r\n"),
2740 };
2741
2742 // The proxy responds to the connect with a 407, using a persistent
2743 // connection.
2744 MockRead data_reads1[] = {
2745 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2746
2747 MockRead("HTTP/1.1 200 OK\r\n"),
2748 MockRead("Content-Length: 1\r\n\r\n"),
2749 MockRead(SYNCHRONOUS, "1"),
2750
2751 MockRead("HTTP/1.1 200 OK\r\n"),
2752 MockRead("Content-Length: 2\r\n\r\n"),
2753 MockRead(SYNCHRONOUS, "22"),
2754 };
2755
2756 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2757 data_writes1, arraysize(data_writes1));
2758 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2759 SSLSocketDataProvider ssl(ASYNC, OK);
2760 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2761
2762 TestCompletionCallback callback1;
2763 scoped_ptr<HttpTransaction> trans1(
2764 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2765
2766 int rv = trans1->Start(&request1, callback1.callback(), log.bound());
2767 EXPECT_EQ(ERR_IO_PENDING, rv);
2768
2769 rv = callback1.WaitForResult();
2770 EXPECT_EQ(OK, rv);
2771
2772 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
2773 ASSERT_TRUE(response1 != NULL);
2774 ASSERT_TRUE(response1->headers.get() != NULL);
2775 EXPECT_EQ(1, response1->headers->GetContentLength());
2776
2777 LoadTimingInfo load_timing_info1;
2778 EXPECT_TRUE(trans1->GetLoadTimingInfo(&load_timing_info1));
2779 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_SSL_TIMES);
2780
2781 trans1.reset();
2782
2783 TestCompletionCallback callback2;
2784 scoped_ptr<HttpTransaction> trans2(
2785 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2786
2787 rv = trans2->Start(&request2, callback2.callback(), log.bound());
2788 EXPECT_EQ(ERR_IO_PENDING, rv);
2789
2790 rv = callback2.WaitForResult();
2791 EXPECT_EQ(OK, rv);
2792
2793 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
2794 ASSERT_TRUE(response2 != NULL);
2795 ASSERT_TRUE(response2->headers.get() != NULL);
2796 EXPECT_EQ(2, response2->headers->GetContentLength());
2797
2798 LoadTimingInfo load_timing_info2;
2799 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
2800 TestLoadTimingReused(load_timing_info2);
2801
2802 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
2803
2804 trans2.reset();
2805 session->CloseAllConnections();
2806 }
2807
2808 // Test the load timing for HTTPS requests with an HTTP proxy and a PAC script.
TEST_P(HttpNetworkTransactionTest,HttpProxyLoadTimingWithPacTwoRequests)2809 TEST_P(HttpNetworkTransactionTest, HttpProxyLoadTimingWithPacTwoRequests) {
2810 HttpRequestInfo request1;
2811 request1.method = "GET";
2812 request1.url = GURL("https://www.google.com/1");
2813
2814 HttpRequestInfo request2;
2815 request2.method = "GET";
2816 request2.url = GURL("https://www.google.com/2");
2817
2818 // Configure against proxy server "myproxy:70".
2819 session_deps_.proxy_service.reset(
2820 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
2821 CapturingBoundNetLog log;
2822 session_deps_.net_log = log.bound().net_log();
2823 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2824
2825 // Since we have proxy, should try to establish tunnel.
2826 MockWrite data_writes1[] = {
2827 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2828 "Host: www.google.com\r\n"
2829 "Proxy-Connection: keep-alive\r\n\r\n"),
2830
2831 MockWrite("GET /1 HTTP/1.1\r\n"
2832 "Host: www.google.com\r\n"
2833 "Connection: keep-alive\r\n\r\n"),
2834
2835 MockWrite("GET /2 HTTP/1.1\r\n"
2836 "Host: www.google.com\r\n"
2837 "Connection: keep-alive\r\n\r\n"),
2838 };
2839
2840 // The proxy responds to the connect with a 407, using a persistent
2841 // connection.
2842 MockRead data_reads1[] = {
2843 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2844
2845 MockRead("HTTP/1.1 200 OK\r\n"),
2846 MockRead("Content-Length: 1\r\n\r\n"),
2847 MockRead(SYNCHRONOUS, "1"),
2848
2849 MockRead("HTTP/1.1 200 OK\r\n"),
2850 MockRead("Content-Length: 2\r\n\r\n"),
2851 MockRead(SYNCHRONOUS, "22"),
2852 };
2853
2854 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2855 data_writes1, arraysize(data_writes1));
2856 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2857 SSLSocketDataProvider ssl(ASYNC, OK);
2858 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2859
2860 TestCompletionCallback callback1;
2861 scoped_ptr<HttpTransaction> trans1(
2862 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2863
2864 int rv = trans1->Start(&request1, callback1.callback(), log.bound());
2865 EXPECT_EQ(ERR_IO_PENDING, rv);
2866
2867 rv = callback1.WaitForResult();
2868 EXPECT_EQ(OK, rv);
2869
2870 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
2871 ASSERT_TRUE(response1 != NULL);
2872 ASSERT_TRUE(response1->headers.get() != NULL);
2873 EXPECT_EQ(1, response1->headers->GetContentLength());
2874
2875 LoadTimingInfo load_timing_info1;
2876 EXPECT_TRUE(trans1->GetLoadTimingInfo(&load_timing_info1));
2877 TestLoadTimingNotReusedWithPac(load_timing_info1,
2878 CONNECT_TIMING_HAS_SSL_TIMES);
2879
2880 trans1.reset();
2881
2882 TestCompletionCallback callback2;
2883 scoped_ptr<HttpTransaction> trans2(
2884 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2885
2886 rv = trans2->Start(&request2, callback2.callback(), log.bound());
2887 EXPECT_EQ(ERR_IO_PENDING, rv);
2888
2889 rv = callback2.WaitForResult();
2890 EXPECT_EQ(OK, rv);
2891
2892 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
2893 ASSERT_TRUE(response2 != NULL);
2894 ASSERT_TRUE(response2->headers.get() != NULL);
2895 EXPECT_EQ(2, response2->headers->GetContentLength());
2896
2897 LoadTimingInfo load_timing_info2;
2898 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
2899 TestLoadTimingReusedWithPac(load_timing_info2);
2900
2901 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
2902
2903 trans2.reset();
2904 session->CloseAllConnections();
2905 }
2906
2907 // Test a simple get through an HTTPS Proxy.
TEST_P(HttpNetworkTransactionTest,HttpsProxyGet)2908 TEST_P(HttpNetworkTransactionTest, HttpsProxyGet) {
2909 HttpRequestInfo request;
2910 request.method = "GET";
2911 request.url = GURL("http://www.google.com/");
2912
2913 // Configure against https proxy server "proxy:70".
2914 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
2915 "https://proxy:70"));
2916 CapturingBoundNetLog log;
2917 session_deps_.net_log = log.bound().net_log();
2918 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2919
2920 // Since we have proxy, should use full url
2921 MockWrite data_writes1[] = {
2922 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2923 "Host: www.google.com\r\n"
2924 "Proxy-Connection: keep-alive\r\n\r\n"),
2925 };
2926
2927 MockRead data_reads1[] = {
2928 MockRead("HTTP/1.1 200 OK\r\n"),
2929 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2930 MockRead("Content-Length: 100\r\n\r\n"),
2931 MockRead(SYNCHRONOUS, OK),
2932 };
2933
2934 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2935 data_writes1, arraysize(data_writes1));
2936 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2937 SSLSocketDataProvider ssl(ASYNC, OK);
2938 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2939
2940 TestCompletionCallback callback1;
2941
2942 scoped_ptr<HttpTransaction> trans(
2943 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2944
2945 int rv = trans->Start(&request, callback1.callback(), log.bound());
2946 EXPECT_EQ(ERR_IO_PENDING, rv);
2947
2948 rv = callback1.WaitForResult();
2949 EXPECT_EQ(OK, rv);
2950
2951 LoadTimingInfo load_timing_info;
2952 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
2953 TestLoadTimingNotReused(load_timing_info,
2954 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
2955
2956 const HttpResponseInfo* response = trans->GetResponseInfo();
2957 ASSERT_TRUE(response != NULL);
2958
2959 EXPECT_TRUE(response->headers->IsKeepAlive());
2960 EXPECT_EQ(200, response->headers->response_code());
2961 EXPECT_EQ(100, response->headers->GetContentLength());
2962 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2963
2964 // The password prompt info should not be set.
2965 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2966 }
2967
2968 // Test a SPDY get through an HTTPS Proxy.
TEST_P(HttpNetworkTransactionTest,HttpsProxySpdyGet)2969 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGet) {
2970 HttpRequestInfo request;
2971 request.method = "GET";
2972 request.url = GURL("http://www.google.com/");
2973 request.load_flags = 0;
2974
2975 // Configure against https proxy server "proxy:70".
2976 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
2977 "https://proxy:70"));
2978 CapturingBoundNetLog log;
2979 session_deps_.net_log = log.bound().net_log();
2980 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2981
2982 // fetch http://www.google.com/ via SPDY
2983 scoped_ptr<SpdyFrame> req(
2984 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
2985 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
2986
2987 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2988 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
2989 MockRead spdy_reads[] = {
2990 CreateMockRead(*resp),
2991 CreateMockRead(*data),
2992 MockRead(ASYNC, 0, 0),
2993 };
2994
2995 DelayedSocketData spdy_data(
2996 1, // wait for one write to finish before reading.
2997 spdy_reads, arraysize(spdy_reads),
2998 spdy_writes, arraysize(spdy_writes));
2999 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
3000
3001 SSLSocketDataProvider ssl(ASYNC, OK);
3002 ssl.SetNextProto(GetParam());
3003 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3004
3005 TestCompletionCallback callback1;
3006
3007 scoped_ptr<HttpTransaction> trans(
3008 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3009
3010 int rv = trans->Start(&request, callback1.callback(), log.bound());
3011 EXPECT_EQ(ERR_IO_PENDING, rv);
3012
3013 rv = callback1.WaitForResult();
3014 EXPECT_EQ(OK, rv);
3015
3016 LoadTimingInfo load_timing_info;
3017 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3018 TestLoadTimingNotReused(load_timing_info,
3019 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
3020
3021 const HttpResponseInfo* response = trans->GetResponseInfo();
3022 ASSERT_TRUE(response != NULL);
3023 ASSERT_TRUE(response->headers.get() != NULL);
3024 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3025
3026 std::string response_data;
3027 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
3028 EXPECT_EQ(kUploadData, response_data);
3029 }
3030
3031 // Verifies that a session which races and wins against the owning transaction
3032 // (completing prior to host resolution), doesn't fail the transaction.
3033 // Regression test for crbug.com/334413.
TEST_P(HttpNetworkTransactionTest,HttpsProxySpdyGetWithSessionRace)3034 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGetWithSessionRace) {
3035 HttpRequestInfo request;
3036 request.method = "GET";
3037 request.url = GURL("http://www.google.com/");
3038 request.load_flags = 0;
3039
3040 // Configure SPDY proxy server "proxy:70".
3041 session_deps_.proxy_service.reset(
3042 ProxyService::CreateFixed("https://proxy:70"));
3043 CapturingBoundNetLog log;
3044 session_deps_.net_log = log.bound().net_log();
3045 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3046
3047 // Fetch http://www.google.com/ through the SPDY proxy.
3048 scoped_ptr<SpdyFrame> req(
3049 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
3050 MockWrite spdy_writes[] = {CreateMockWrite(*req)};
3051
3052 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3053 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
3054 MockRead spdy_reads[] = {
3055 CreateMockRead(*resp), CreateMockRead(*data), MockRead(ASYNC, 0, 0),
3056 };
3057
3058 DelayedSocketData spdy_data(
3059 1, // wait for one write to finish before reading.
3060 spdy_reads,
3061 arraysize(spdy_reads),
3062 spdy_writes,
3063 arraysize(spdy_writes));
3064 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
3065
3066 SSLSocketDataProvider ssl(ASYNC, OK);
3067 ssl.SetNextProto(GetParam());
3068 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3069
3070 TestCompletionCallback callback1;
3071
3072 scoped_ptr<HttpTransaction> trans(
3073 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3074
3075 // Stall the hostname resolution begun by the transaction.
3076 session_deps_.host_resolver->set_synchronous_mode(false);
3077 session_deps_.host_resolver->set_ondemand_mode(true);
3078
3079 int rv = trans->Start(&request, callback1.callback(), log.bound());
3080 EXPECT_EQ(ERR_IO_PENDING, rv);
3081
3082 // Race a session to the proxy, which completes first.
3083 session_deps_.host_resolver->set_ondemand_mode(false);
3084 SpdySessionKey key(
3085 HostPortPair("proxy", 70), ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
3086 base::WeakPtr<SpdySession> spdy_session =
3087 CreateSecureSpdySession(session, key, log.bound());
3088
3089 // Unstall the resolution begun by the transaction.
3090 session_deps_.host_resolver->set_ondemand_mode(true);
3091 session_deps_.host_resolver->ResolveAllPending();
3092
3093 EXPECT_FALSE(callback1.have_result());
3094 rv = callback1.WaitForResult();
3095 EXPECT_EQ(OK, rv);
3096
3097 const HttpResponseInfo* response = trans->GetResponseInfo();
3098 ASSERT_TRUE(response != NULL);
3099 ASSERT_TRUE(response->headers.get() != NULL);
3100 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3101
3102 std::string response_data;
3103 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
3104 EXPECT_EQ(kUploadData, response_data);
3105 }
3106
3107 // Test a SPDY get through an HTTPS Proxy.
TEST_P(HttpNetworkTransactionTest,HttpsProxySpdyGetWithProxyAuth)3108 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGetWithProxyAuth) {
3109 HttpRequestInfo request;
3110 request.method = "GET";
3111 request.url = GURL("http://www.google.com/");
3112 request.load_flags = 0;
3113
3114 // Configure against https proxy server "myproxy:70".
3115 session_deps_.proxy_service.reset(
3116 ProxyService::CreateFixed("https://myproxy:70"));
3117 CapturingBoundNetLog log;
3118 session_deps_.net_log = log.bound().net_log();
3119 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3120
3121 // The first request will be a bare GET, the second request will be a
3122 // GET with a Proxy-Authorization header.
3123 scoped_ptr<SpdyFrame> req_get(
3124 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
3125 const char* const kExtraAuthorizationHeaders[] = {
3126 "proxy-authorization", "Basic Zm9vOmJhcg=="
3127 };
3128 scoped_ptr<SpdyFrame> req_get_authorization(
3129 spdy_util_.ConstructSpdyGet(kExtraAuthorizationHeaders,
3130 arraysize(kExtraAuthorizationHeaders) / 2,
3131 false,
3132 3,
3133 LOWEST,
3134 false));
3135 MockWrite spdy_writes[] = {
3136 CreateMockWrite(*req_get, 1),
3137 CreateMockWrite(*req_get_authorization, 4),
3138 };
3139
3140 // The first response is a 407 proxy authentication challenge, and the second
3141 // response will be a 200 response since the second request includes a valid
3142 // Authorization header.
3143 const char* const kExtraAuthenticationHeaders[] = {
3144 "proxy-authenticate", "Basic realm=\"MyRealm1\""
3145 };
3146 scoped_ptr<SpdyFrame> resp_authentication(
3147 spdy_util_.ConstructSpdySynReplyError(
3148 "407 Proxy Authentication Required",
3149 kExtraAuthenticationHeaders, arraysize(kExtraAuthenticationHeaders)/2,
3150 1));
3151 scoped_ptr<SpdyFrame> body_authentication(
3152 spdy_util_.ConstructSpdyBodyFrame(1, true));
3153 scoped_ptr<SpdyFrame> resp_data(
3154 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
3155 scoped_ptr<SpdyFrame> body_data(spdy_util_.ConstructSpdyBodyFrame(3, true));
3156 MockRead spdy_reads[] = {
3157 CreateMockRead(*resp_authentication, 2),
3158 CreateMockRead(*body_authentication, 3),
3159 CreateMockRead(*resp_data, 5),
3160 CreateMockRead(*body_data, 6),
3161 MockRead(ASYNC, 0, 7),
3162 };
3163
3164 OrderedSocketData data(
3165 spdy_reads, arraysize(spdy_reads),
3166 spdy_writes, arraysize(spdy_writes));
3167 session_deps_.socket_factory->AddSocketDataProvider(&data);
3168
3169 SSLSocketDataProvider ssl(ASYNC, OK);
3170 ssl.SetNextProto(GetParam());
3171 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3172
3173 TestCompletionCallback callback1;
3174
3175 scoped_ptr<HttpTransaction> trans(
3176 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3177
3178 int rv = trans->Start(&request, callback1.callback(), log.bound());
3179 EXPECT_EQ(ERR_IO_PENDING, rv);
3180
3181 rv = callback1.WaitForResult();
3182 EXPECT_EQ(OK, rv);
3183
3184 const HttpResponseInfo* const response = trans->GetResponseInfo();
3185
3186 ASSERT_TRUE(response != NULL);
3187 ASSERT_TRUE(response->headers.get() != NULL);
3188 EXPECT_EQ(407, response->headers->response_code());
3189 EXPECT_TRUE(response->was_fetched_via_spdy);
3190 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
3191
3192 TestCompletionCallback callback2;
3193
3194 rv = trans->RestartWithAuth(
3195 AuthCredentials(kFoo, kBar), callback2.callback());
3196 EXPECT_EQ(ERR_IO_PENDING, rv);
3197
3198 rv = callback2.WaitForResult();
3199 EXPECT_EQ(OK, rv);
3200
3201 const HttpResponseInfo* const response_restart = trans->GetResponseInfo();
3202
3203 ASSERT_TRUE(response_restart != NULL);
3204 ASSERT_TRUE(response_restart->headers.get() != NULL);
3205 EXPECT_EQ(200, response_restart->headers->response_code());
3206 // The password prompt info should not be set.
3207 EXPECT_TRUE(response_restart->auth_challenge.get() == NULL);
3208 }
3209
3210 // Test a SPDY CONNECT through an HTTPS Proxy to an HTTPS (non-SPDY) Server.
TEST_P(HttpNetworkTransactionTest,HttpsProxySpdyConnectHttps)3211 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectHttps) {
3212 HttpRequestInfo request;
3213 request.method = "GET";
3214 request.url = GURL("https://www.google.com/");
3215 request.load_flags = 0;
3216
3217 // Configure against https proxy server "proxy:70".
3218 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3219 "https://proxy:70"));
3220 CapturingBoundNetLog log;
3221 session_deps_.net_log = log.bound().net_log();
3222 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3223
3224 scoped_ptr<HttpTransaction> trans(
3225 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3226
3227 // CONNECT to www.google.com:443 via SPDY
3228 scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(NULL, 0, 1,
3229 LOWEST));
3230 // fetch https://www.google.com/ via HTTP
3231
3232 const char get[] = "GET / HTTP/1.1\r\n"
3233 "Host: www.google.com\r\n"
3234 "Connection: keep-alive\r\n\r\n";
3235 scoped_ptr<SpdyFrame> wrapped_get(
3236 spdy_util_.ConstructSpdyBodyFrame(1, get, strlen(get), false));
3237 scoped_ptr<SpdyFrame> conn_resp(
3238 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3239 const char resp[] = "HTTP/1.1 200 OK\r\n"
3240 "Content-Length: 10\r\n\r\n";
3241 scoped_ptr<SpdyFrame> wrapped_get_resp(
3242 spdy_util_.ConstructSpdyBodyFrame(1, resp, strlen(resp), false));
3243 scoped_ptr<SpdyFrame> wrapped_body(
3244 spdy_util_.ConstructSpdyBodyFrame(1, "1234567890", 10, false));
3245 scoped_ptr<SpdyFrame> window_update(
3246 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp->size()));
3247
3248 MockWrite spdy_writes[] = {
3249 CreateMockWrite(*connect, 1),
3250 CreateMockWrite(*wrapped_get, 3),
3251 CreateMockWrite(*window_update, 5),
3252 };
3253
3254 MockRead spdy_reads[] = {
3255 CreateMockRead(*conn_resp, 2, ASYNC),
3256 CreateMockRead(*wrapped_get_resp, 4, ASYNC),
3257 CreateMockRead(*wrapped_body, 6, ASYNC),
3258 CreateMockRead(*wrapped_body, 7, ASYNC),
3259 MockRead(ASYNC, 0, 8),
3260 };
3261
3262 OrderedSocketData spdy_data(
3263 spdy_reads, arraysize(spdy_reads),
3264 spdy_writes, arraysize(spdy_writes));
3265 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
3266
3267 SSLSocketDataProvider ssl(ASYNC, OK);
3268 ssl.SetNextProto(GetParam());
3269 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3270 SSLSocketDataProvider ssl2(ASYNC, OK);
3271 ssl2.was_npn_negotiated = false;
3272 ssl2.protocol_negotiated = kProtoUnknown;
3273 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
3274
3275 TestCompletionCallback callback1;
3276
3277 int rv = trans->Start(&request, callback1.callback(), log.bound());
3278 EXPECT_EQ(ERR_IO_PENDING, rv);
3279
3280 rv = callback1.WaitForResult();
3281 EXPECT_EQ(OK, rv);
3282
3283 LoadTimingInfo load_timing_info;
3284 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3285 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
3286
3287 const HttpResponseInfo* response = trans->GetResponseInfo();
3288 ASSERT_TRUE(response != NULL);
3289 ASSERT_TRUE(response->headers.get() != NULL);
3290 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3291
3292 std::string response_data;
3293 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
3294 EXPECT_EQ("1234567890", response_data);
3295 }
3296
3297 // Test a SPDY CONNECT through an HTTPS Proxy to a SPDY server.
TEST_P(HttpNetworkTransactionTest,HttpsProxySpdyConnectSpdy)3298 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectSpdy) {
3299 HttpRequestInfo request;
3300 request.method = "GET";
3301 request.url = GURL("https://www.google.com/");
3302 request.load_flags = 0;
3303
3304 // Configure against https proxy server "proxy:70".
3305 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3306 "https://proxy:70"));
3307 CapturingBoundNetLog log;
3308 session_deps_.net_log = log.bound().net_log();
3309 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3310
3311 scoped_ptr<HttpTransaction> trans(
3312 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3313
3314 // CONNECT to www.google.com:443 via SPDY
3315 scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(NULL, 0, 1,
3316 LOWEST));
3317 // fetch https://www.google.com/ via SPDY
3318 const char* const kMyUrl = "https://www.google.com/";
3319 scoped_ptr<SpdyFrame> get(
3320 spdy_util_.ConstructSpdyGet(kMyUrl, false, 1, LOWEST));
3321 scoped_ptr<SpdyFrame> wrapped_get(
3322 spdy_util_.ConstructWrappedSpdyFrame(get, 1));
3323 scoped_ptr<SpdyFrame> conn_resp(
3324 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3325 scoped_ptr<SpdyFrame> get_resp(
3326 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3327 scoped_ptr<SpdyFrame> wrapped_get_resp(
3328 spdy_util_.ConstructWrappedSpdyFrame(get_resp, 1));
3329 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
3330 scoped_ptr<SpdyFrame> wrapped_body(
3331 spdy_util_.ConstructWrappedSpdyFrame(body, 1));
3332 scoped_ptr<SpdyFrame> window_update_get_resp(
3333 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp->size()));
3334 scoped_ptr<SpdyFrame> window_update_body(
3335 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_body->size()));
3336
3337 MockWrite spdy_writes[] = {
3338 CreateMockWrite(*connect, 1),
3339 CreateMockWrite(*wrapped_get, 3),
3340 CreateMockWrite(*window_update_get_resp, 5),
3341 CreateMockWrite(*window_update_body, 7),
3342 };
3343
3344 MockRead spdy_reads[] = {
3345 CreateMockRead(*conn_resp, 2, ASYNC),
3346 CreateMockRead(*wrapped_get_resp, 4, ASYNC),
3347 CreateMockRead(*wrapped_body, 6, ASYNC),
3348 MockRead(ASYNC, 0, 8),
3349 };
3350
3351 OrderedSocketData spdy_data(
3352 spdy_reads, arraysize(spdy_reads),
3353 spdy_writes, arraysize(spdy_writes));
3354 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
3355
3356 SSLSocketDataProvider ssl(ASYNC, OK);
3357 ssl.SetNextProto(GetParam());
3358 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3359 SSLSocketDataProvider ssl2(ASYNC, OK);
3360 ssl2.SetNextProto(GetParam());
3361 ssl2.protocol_negotiated = GetParam();
3362 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
3363
3364 TestCompletionCallback callback1;
3365
3366 int rv = trans->Start(&request, callback1.callback(), log.bound());
3367 EXPECT_EQ(ERR_IO_PENDING, rv);
3368
3369 rv = callback1.WaitForResult();
3370 EXPECT_EQ(OK, rv);
3371
3372 LoadTimingInfo load_timing_info;
3373 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3374 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
3375
3376 const HttpResponseInfo* response = trans->GetResponseInfo();
3377 ASSERT_TRUE(response != NULL);
3378 ASSERT_TRUE(response->headers.get() != NULL);
3379 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3380
3381 std::string response_data;
3382 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
3383 EXPECT_EQ(kUploadData, response_data);
3384 }
3385
3386 // Test a SPDY CONNECT failure through an HTTPS Proxy.
TEST_P(HttpNetworkTransactionTest,HttpsProxySpdyConnectFailure)3387 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectFailure) {
3388 HttpRequestInfo request;
3389 request.method = "GET";
3390 request.url = GURL("https://www.google.com/");
3391 request.load_flags = 0;
3392
3393 // Configure against https proxy server "proxy:70".
3394 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3395 "https://proxy:70"));
3396 CapturingBoundNetLog log;
3397 session_deps_.net_log = log.bound().net_log();
3398 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3399
3400 scoped_ptr<HttpTransaction> trans(
3401 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3402
3403 // CONNECT to www.google.com:443 via SPDY
3404 scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(NULL, 0, 1,
3405 LOWEST));
3406 scoped_ptr<SpdyFrame> get(
3407 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
3408
3409 MockWrite spdy_writes[] = {
3410 CreateMockWrite(*connect, 1),
3411 CreateMockWrite(*get, 3),
3412 };
3413
3414 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdySynReplyError(1));
3415 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
3416 MockRead spdy_reads[] = {
3417 CreateMockRead(*resp, 2, ASYNC),
3418 MockRead(ASYNC, 0, 4),
3419 };
3420
3421 OrderedSocketData spdy_data(
3422 spdy_reads, arraysize(spdy_reads),
3423 spdy_writes, arraysize(spdy_writes));
3424 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
3425
3426 SSLSocketDataProvider ssl(ASYNC, OK);
3427 ssl.SetNextProto(GetParam());
3428 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3429 SSLSocketDataProvider ssl2(ASYNC, OK);
3430 ssl2.SetNextProto(GetParam());
3431 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
3432
3433 TestCompletionCallback callback1;
3434
3435 int rv = trans->Start(&request, callback1.callback(), log.bound());
3436 EXPECT_EQ(ERR_IO_PENDING, rv);
3437
3438 rv = callback1.WaitForResult();
3439 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
3440
3441 // TODO(ttuttle): Anything else to check here?
3442 }
3443
3444 // Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
3445 // HTTPS Proxy to different servers.
TEST_P(HttpNetworkTransactionTest,HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsTwoServers)3446 TEST_P(HttpNetworkTransactionTest,
3447 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsTwoServers) {
3448 // Configure against https proxy server "proxy:70".
3449 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3450 "https://proxy:70"));
3451 CapturingBoundNetLog log;
3452 session_deps_.net_log = log.bound().net_log();
3453 scoped_refptr<HttpNetworkSession> session(
3454 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
3455
3456 HttpRequestInfo request1;
3457 request1.method = "GET";
3458 request1.url = GURL("https://www.google.com/");
3459 request1.load_flags = 0;
3460
3461 HttpRequestInfo request2;
3462 request2.method = "GET";
3463 request2.url = GURL("https://news.google.com/");
3464 request2.load_flags = 0;
3465
3466 // CONNECT to www.google.com:443 via SPDY.
3467 scoped_ptr<SpdyFrame> connect1(spdy_util_.ConstructSpdyConnect(NULL, 0, 1,
3468 LOWEST));
3469 scoped_ptr<SpdyFrame> conn_resp1(
3470 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3471
3472 // Fetch https://www.google.com/ via HTTP.
3473 const char get1[] = "GET / HTTP/1.1\r\n"
3474 "Host: www.google.com\r\n"
3475 "Connection: keep-alive\r\n\r\n";
3476 scoped_ptr<SpdyFrame> wrapped_get1(
3477 spdy_util_.ConstructSpdyBodyFrame(1, get1, strlen(get1), false));
3478 const char resp1[] = "HTTP/1.1 200 OK\r\n"
3479 "Content-Length: 1\r\n\r\n";
3480 scoped_ptr<SpdyFrame> wrapped_get_resp1(
3481 spdy_util_.ConstructSpdyBodyFrame(1, resp1, strlen(resp1), false));
3482 scoped_ptr<SpdyFrame> wrapped_body1(
3483 spdy_util_.ConstructSpdyBodyFrame(1, "1", 1, false));
3484 scoped_ptr<SpdyFrame> window_update(
3485 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp1->size()));
3486
3487 // CONNECT to news.google.com:443 via SPDY.
3488 SpdySynStreamIR connect2_ir(3);
3489 spdy_util_.SetPriority(LOWEST, &connect2_ir);
3490 connect2_ir.SetHeader(spdy_util_.GetMethodKey(), "CONNECT");
3491 connect2_ir.SetHeader(spdy_util_.GetPathKey(), "news.google.com:443");
3492 connect2_ir.SetHeader(spdy_util_.GetHostKey(), "news.google.com");
3493 spdy_util_.MaybeAddVersionHeader(&connect2_ir);
3494 scoped_ptr<SpdyFrame> connect2(
3495 spdy_util_.CreateFramer(false)->SerializeFrame(connect2_ir));
3496
3497 scoped_ptr<SpdyFrame> conn_resp2(
3498 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
3499
3500 // Fetch https://news.google.com/ via HTTP.
3501 const char get2[] = "GET / HTTP/1.1\r\n"
3502 "Host: news.google.com\r\n"
3503 "Connection: keep-alive\r\n\r\n";
3504 scoped_ptr<SpdyFrame> wrapped_get2(
3505 spdy_util_.ConstructSpdyBodyFrame(3, get2, strlen(get2), false));
3506 const char resp2[] = "HTTP/1.1 200 OK\r\n"
3507 "Content-Length: 2\r\n\r\n";
3508 scoped_ptr<SpdyFrame> wrapped_get_resp2(
3509 spdy_util_.ConstructSpdyBodyFrame(3, resp2, strlen(resp2), false));
3510 scoped_ptr<SpdyFrame> wrapped_body2(
3511 spdy_util_.ConstructSpdyBodyFrame(3, "22", 2, false));
3512
3513 MockWrite spdy_writes[] = {
3514 CreateMockWrite(*connect1, 0),
3515 CreateMockWrite(*wrapped_get1, 2),
3516 CreateMockWrite(*connect2, 5),
3517 CreateMockWrite(*wrapped_get2, 7),
3518 };
3519
3520 MockRead spdy_reads[] = {
3521 CreateMockRead(*conn_resp1, 1, ASYNC),
3522 CreateMockRead(*wrapped_get_resp1, 3, ASYNC),
3523 CreateMockRead(*wrapped_body1, 4, ASYNC),
3524 CreateMockRead(*conn_resp2, 6, ASYNC),
3525 CreateMockRead(*wrapped_get_resp2, 8, ASYNC),
3526 CreateMockRead(*wrapped_body2, 9, ASYNC),
3527 MockRead(ASYNC, 0, 10),
3528 };
3529
3530 DeterministicSocketData spdy_data(
3531 spdy_reads, arraysize(spdy_reads),
3532 spdy_writes, arraysize(spdy_writes));
3533 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&spdy_data);
3534
3535 SSLSocketDataProvider ssl(ASYNC, OK);
3536 ssl.SetNextProto(GetParam());
3537 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
3538 SSLSocketDataProvider ssl2(ASYNC, OK);
3539 ssl2.was_npn_negotiated = false;
3540 ssl2.protocol_negotiated = kProtoUnknown;
3541 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2);
3542 SSLSocketDataProvider ssl3(ASYNC, OK);
3543 ssl3.was_npn_negotiated = false;
3544 ssl3.protocol_negotiated = kProtoUnknown;
3545 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl3);
3546
3547 TestCompletionCallback callback;
3548
3549 scoped_ptr<HttpTransaction> trans(
3550 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3551 int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
3552 EXPECT_EQ(ERR_IO_PENDING, rv);
3553 // The first connect and request, each of their responses, and the body.
3554 spdy_data.RunFor(5);
3555
3556 rv = callback.WaitForResult();
3557 EXPECT_EQ(OK, rv);
3558
3559 LoadTimingInfo load_timing_info;
3560 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3561 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
3562
3563 const HttpResponseInfo* response = trans->GetResponseInfo();
3564 ASSERT_TRUE(response != NULL);
3565 ASSERT_TRUE(response->headers.get() != NULL);
3566 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3567
3568 std::string response_data;
3569 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(256));
3570 EXPECT_EQ(1, trans->Read(buf.get(), 256, callback.callback()));
3571
3572 scoped_ptr<HttpTransaction> trans2(
3573 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3574 rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
3575 EXPECT_EQ(ERR_IO_PENDING, rv);
3576
3577 // The second connect and request, each of their responses, and the body.
3578 spdy_data.RunFor(5);
3579 rv = callback.WaitForResult();
3580 EXPECT_EQ(OK, rv);
3581
3582 LoadTimingInfo load_timing_info2;
3583 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
3584 // Even though the SPDY connection is reused, a new tunnelled connection has
3585 // to be created, so the socket's load timing looks like a fresh connection.
3586 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_SSL_TIMES);
3587
3588 // The requests should have different IDs, since they each are using their own
3589 // separate stream.
3590 EXPECT_NE(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
3591
3592 EXPECT_EQ(2, trans2->Read(buf.get(), 256, callback.callback()));
3593 }
3594
3595 // Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
3596 // HTTPS Proxy to the same server.
TEST_P(HttpNetworkTransactionTest,HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsSameServer)3597 TEST_P(HttpNetworkTransactionTest,
3598 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsSameServer) {
3599 // Configure against https proxy server "proxy:70".
3600 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3601 "https://proxy:70"));
3602 CapturingBoundNetLog log;
3603 session_deps_.net_log = log.bound().net_log();
3604 scoped_refptr<HttpNetworkSession> session(
3605 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
3606
3607 HttpRequestInfo request1;
3608 request1.method = "GET";
3609 request1.url = GURL("https://www.google.com/");
3610 request1.load_flags = 0;
3611
3612 HttpRequestInfo request2;
3613 request2.method = "GET";
3614 request2.url = GURL("https://www.google.com/2");
3615 request2.load_flags = 0;
3616
3617 // CONNECT to www.google.com:443 via SPDY.
3618 scoped_ptr<SpdyFrame> connect1(spdy_util_.ConstructSpdyConnect(NULL, 0, 1,
3619 LOWEST));
3620 scoped_ptr<SpdyFrame> conn_resp1(
3621 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3622
3623 // Fetch https://www.google.com/ via HTTP.
3624 const char get1[] = "GET / HTTP/1.1\r\n"
3625 "Host: www.google.com\r\n"
3626 "Connection: keep-alive\r\n\r\n";
3627 scoped_ptr<SpdyFrame> wrapped_get1(
3628 spdy_util_.ConstructSpdyBodyFrame(1, get1, strlen(get1), false));
3629 const char resp1[] = "HTTP/1.1 200 OK\r\n"
3630 "Content-Length: 1\r\n\r\n";
3631 scoped_ptr<SpdyFrame> wrapped_get_resp1(
3632 spdy_util_.ConstructSpdyBodyFrame(1, resp1, strlen(resp1), false));
3633 scoped_ptr<SpdyFrame> wrapped_body1(
3634 spdy_util_.ConstructSpdyBodyFrame(1, "1", 1, false));
3635 scoped_ptr<SpdyFrame> window_update(
3636 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp1->size()));
3637
3638 // Fetch https://www.google.com/2 via HTTP.
3639 const char get2[] = "GET /2 HTTP/1.1\r\n"
3640 "Host: www.google.com\r\n"
3641 "Connection: keep-alive\r\n\r\n";
3642 scoped_ptr<SpdyFrame> wrapped_get2(
3643 spdy_util_.ConstructSpdyBodyFrame(1, get2, strlen(get2), false));
3644 const char resp2[] = "HTTP/1.1 200 OK\r\n"
3645 "Content-Length: 2\r\n\r\n";
3646 scoped_ptr<SpdyFrame> wrapped_get_resp2(
3647 spdy_util_.ConstructSpdyBodyFrame(1, resp2, strlen(resp2), false));
3648 scoped_ptr<SpdyFrame> wrapped_body2(
3649 spdy_util_.ConstructSpdyBodyFrame(1, "22", 2, false));
3650
3651 MockWrite spdy_writes[] = {
3652 CreateMockWrite(*connect1, 0),
3653 CreateMockWrite(*wrapped_get1, 2),
3654 CreateMockWrite(*wrapped_get2, 5),
3655 };
3656
3657 MockRead spdy_reads[] = {
3658 CreateMockRead(*conn_resp1, 1, ASYNC),
3659 CreateMockRead(*wrapped_get_resp1, 3, ASYNC),
3660 CreateMockRead(*wrapped_body1, 4, ASYNC),
3661 CreateMockRead(*wrapped_get_resp2, 6, ASYNC),
3662 CreateMockRead(*wrapped_body2, 7, ASYNC),
3663 MockRead(ASYNC, 0, 8),
3664 };
3665
3666 DeterministicSocketData spdy_data(
3667 spdy_reads, arraysize(spdy_reads),
3668 spdy_writes, arraysize(spdy_writes));
3669 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&spdy_data);
3670
3671 SSLSocketDataProvider ssl(ASYNC, OK);
3672 ssl.SetNextProto(GetParam());
3673 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
3674 SSLSocketDataProvider ssl2(ASYNC, OK);
3675 ssl2.was_npn_negotiated = false;
3676 ssl2.protocol_negotiated = kProtoUnknown;
3677 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2);
3678
3679 TestCompletionCallback callback;
3680
3681 scoped_ptr<HttpTransaction> trans(
3682 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3683 int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
3684 EXPECT_EQ(ERR_IO_PENDING, rv);
3685 // The first connect and request, each of their responses, and the body.
3686 spdy_data.RunFor(5);
3687
3688 rv = callback.WaitForResult();
3689 EXPECT_EQ(OK, rv);
3690
3691 LoadTimingInfo load_timing_info;
3692 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3693 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
3694
3695 const HttpResponseInfo* response = trans->GetResponseInfo();
3696 ASSERT_TRUE(response != NULL);
3697 ASSERT_TRUE(response->headers.get() != NULL);
3698 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3699
3700 std::string response_data;
3701 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(256));
3702 EXPECT_EQ(1, trans->Read(buf.get(), 256, callback.callback()));
3703 trans.reset();
3704
3705 scoped_ptr<HttpTransaction> trans2(
3706 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3707 rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
3708 EXPECT_EQ(ERR_IO_PENDING, rv);
3709
3710 // The second request, response, and body. There should not be a second
3711 // connect.
3712 spdy_data.RunFor(3);
3713 rv = callback.WaitForResult();
3714 EXPECT_EQ(OK, rv);
3715
3716 LoadTimingInfo load_timing_info2;
3717 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
3718 TestLoadTimingReused(load_timing_info2);
3719
3720 // The requests should have the same ID.
3721 EXPECT_EQ(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
3722
3723 EXPECT_EQ(2, trans2->Read(buf.get(), 256, callback.callback()));
3724 }
3725
3726 // Test load timing in the case of of two HTTP requests through a SPDY HTTPS
3727 // Proxy to different servers.
TEST_P(HttpNetworkTransactionTest,HttpsProxySpdyLoadTimingTwoHttpRequests)3728 TEST_P(HttpNetworkTransactionTest,
3729 HttpsProxySpdyLoadTimingTwoHttpRequests) {
3730 // Configure against https proxy server "proxy:70".
3731 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3732 "https://proxy:70"));
3733 CapturingBoundNetLog log;
3734 session_deps_.net_log = log.bound().net_log();
3735 scoped_refptr<HttpNetworkSession> session(
3736 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
3737
3738 HttpRequestInfo request1;
3739 request1.method = "GET";
3740 request1.url = GURL("http://www.google.com/");
3741 request1.load_flags = 0;
3742
3743 HttpRequestInfo request2;
3744 request2.method = "GET";
3745 request2.url = GURL("http://news.google.com/");
3746 request2.load_flags = 0;
3747
3748 // http://www.google.com/
3749 scoped_ptr<SpdyHeaderBlock> headers(
3750 spdy_util_.ConstructGetHeaderBlockForProxy("http://www.google.com/"));
3751 scoped_ptr<SpdyFrame> get1(spdy_util_.ConstructSpdyControlFrame(
3752 headers.Pass(), false, 1, LOWEST, SYN_STREAM, CONTROL_FLAG_FIN, 0));
3753 scoped_ptr<SpdyFrame> get_resp1(
3754 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3755 scoped_ptr<SpdyFrame> body1(
3756 spdy_util_.ConstructSpdyBodyFrame(1, "1", 1, true));
3757
3758 // http://news.google.com/
3759 scoped_ptr<SpdyHeaderBlock> headers2(
3760 spdy_util_.ConstructGetHeaderBlockForProxy("http://news.google.com/"));
3761 scoped_ptr<SpdyFrame> get2(spdy_util_.ConstructSpdyControlFrame(
3762 headers2.Pass(), false, 3, LOWEST, SYN_STREAM, CONTROL_FLAG_FIN, 0));
3763 scoped_ptr<SpdyFrame> get_resp2(
3764 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
3765 scoped_ptr<SpdyFrame> body2(
3766 spdy_util_.ConstructSpdyBodyFrame(3, "22", 2, true));
3767
3768 MockWrite spdy_writes[] = {
3769 CreateMockWrite(*get1, 0),
3770 CreateMockWrite(*get2, 3),
3771 };
3772
3773 MockRead spdy_reads[] = {
3774 CreateMockRead(*get_resp1, 1, ASYNC),
3775 CreateMockRead(*body1, 2, ASYNC),
3776 CreateMockRead(*get_resp2, 4, ASYNC),
3777 CreateMockRead(*body2, 5, ASYNC),
3778 MockRead(ASYNC, 0, 6),
3779 };
3780
3781 DeterministicSocketData spdy_data(
3782 spdy_reads, arraysize(spdy_reads),
3783 spdy_writes, arraysize(spdy_writes));
3784 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&spdy_data);
3785
3786 SSLSocketDataProvider ssl(ASYNC, OK);
3787 ssl.SetNextProto(GetParam());
3788 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
3789
3790 TestCompletionCallback callback;
3791
3792 scoped_ptr<HttpTransaction> trans(
3793 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3794 int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
3795 EXPECT_EQ(ERR_IO_PENDING, rv);
3796 spdy_data.RunFor(2);
3797
3798 rv = callback.WaitForResult();
3799 EXPECT_EQ(OK, rv);
3800
3801 LoadTimingInfo load_timing_info;
3802 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3803 TestLoadTimingNotReused(load_timing_info,
3804 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
3805
3806 const HttpResponseInfo* response = trans->GetResponseInfo();
3807 ASSERT_TRUE(response != NULL);
3808 ASSERT_TRUE(response->headers.get() != NULL);
3809 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3810
3811 std::string response_data;
3812 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(256));
3813 EXPECT_EQ(ERR_IO_PENDING, trans->Read(buf.get(), 256, callback.callback()));
3814 spdy_data.RunFor(1);
3815 EXPECT_EQ(1, callback.WaitForResult());
3816 // Delete the first request, so the second one can reuse the socket.
3817 trans.reset();
3818
3819 scoped_ptr<HttpTransaction> trans2(
3820 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3821 rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
3822 EXPECT_EQ(ERR_IO_PENDING, rv);
3823
3824 spdy_data.RunFor(2);
3825 rv = callback.WaitForResult();
3826 EXPECT_EQ(OK, rv);
3827
3828 LoadTimingInfo load_timing_info2;
3829 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
3830 TestLoadTimingReused(load_timing_info2);
3831
3832 // The requests should have the same ID.
3833 EXPECT_EQ(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
3834
3835 EXPECT_EQ(ERR_IO_PENDING, trans2->Read(buf.get(), 256, callback.callback()));
3836 spdy_data.RunFor(1);
3837 EXPECT_EQ(2, callback.WaitForResult());
3838 }
3839
3840 // Test the challenge-response-retry sequence through an HTTPS Proxy
TEST_P(HttpNetworkTransactionTest,HttpsProxyAuthRetry)3841 TEST_P(HttpNetworkTransactionTest, HttpsProxyAuthRetry) {
3842 HttpRequestInfo request;
3843 request.method = "GET";
3844 request.url = GURL("http://www.google.com/");
3845 // when the no authentication data flag is set.
3846 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
3847
3848 // Configure against https proxy server "myproxy:70".
3849 session_deps_.proxy_service.reset(
3850 ProxyService::CreateFixed("https://myproxy:70"));
3851 CapturingBoundNetLog log;
3852 session_deps_.net_log = log.bound().net_log();
3853 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3854
3855 // Since we have proxy, should use full url
3856 MockWrite data_writes1[] = {
3857 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
3858 "Host: www.google.com\r\n"
3859 "Proxy-Connection: keep-alive\r\n\r\n"),
3860
3861 // After calling trans->RestartWithAuth(), this is the request we should
3862 // be issuing -- the final header line contains the credentials.
3863 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
3864 "Host: www.google.com\r\n"
3865 "Proxy-Connection: keep-alive\r\n"
3866 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3867 };
3868
3869 // The proxy responds to the GET with a 407, using a persistent
3870 // connection.
3871 MockRead data_reads1[] = {
3872 // No credentials.
3873 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3874 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3875 MockRead("Proxy-Connection: keep-alive\r\n"),
3876 MockRead("Content-Length: 0\r\n\r\n"),
3877
3878 MockRead("HTTP/1.1 200 OK\r\n"),
3879 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3880 MockRead("Content-Length: 100\r\n\r\n"),
3881 MockRead(SYNCHRONOUS, OK),
3882 };
3883
3884 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3885 data_writes1, arraysize(data_writes1));
3886 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3887 SSLSocketDataProvider ssl(ASYNC, OK);
3888 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3889
3890 TestCompletionCallback callback1;
3891
3892 scoped_ptr<HttpTransaction> trans(
3893 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3894
3895 int rv = trans->Start(&request, callback1.callback(), log.bound());
3896 EXPECT_EQ(ERR_IO_PENDING, rv);
3897
3898 rv = callback1.WaitForResult();
3899 EXPECT_EQ(OK, rv);
3900
3901 LoadTimingInfo load_timing_info;
3902 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3903 TestLoadTimingNotReused(load_timing_info,
3904 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
3905
3906 const HttpResponseInfo* response = trans->GetResponseInfo();
3907 ASSERT_TRUE(response != NULL);
3908 ASSERT_FALSE(response->headers.get() == NULL);
3909 EXPECT_EQ(407, response->headers->response_code());
3910 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3911 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
3912
3913 TestCompletionCallback callback2;
3914
3915 rv = trans->RestartWithAuth(
3916 AuthCredentials(kFoo, kBar), callback2.callback());
3917 EXPECT_EQ(ERR_IO_PENDING, rv);
3918
3919 rv = callback2.WaitForResult();
3920 EXPECT_EQ(OK, rv);
3921
3922 load_timing_info = LoadTimingInfo();
3923 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3924 // Retrying with HTTP AUTH is considered to be reusing a socket.
3925 TestLoadTimingReused(load_timing_info);
3926
3927 response = trans->GetResponseInfo();
3928 ASSERT_TRUE(response != NULL);
3929
3930 EXPECT_TRUE(response->headers->IsKeepAlive());
3931 EXPECT_EQ(200, response->headers->response_code());
3932 EXPECT_EQ(100, response->headers->GetContentLength());
3933 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3934
3935 // The password prompt info should not be set.
3936 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3937 }
3938
ConnectStatusHelperWithExpectedStatus(const MockRead & status,int expected_status)3939 void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
3940 const MockRead& status, int expected_status) {
3941 HttpRequestInfo request;
3942 request.method = "GET";
3943 request.url = GURL("https://www.google.com/");
3944 request.load_flags = 0;
3945
3946 // Configure against proxy server "myproxy:70".
3947 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
3948 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3949
3950 // Since we have proxy, should try to establish tunnel.
3951 MockWrite data_writes[] = {
3952 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
3953 "Host: www.google.com\r\n"
3954 "Proxy-Connection: keep-alive\r\n\r\n"),
3955 };
3956
3957 MockRead data_reads[] = {
3958 status,
3959 MockRead("Content-Length: 10\r\n\r\n"),
3960 // No response body because the test stops reading here.
3961 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
3962 };
3963
3964 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3965 data_writes, arraysize(data_writes));
3966 session_deps_.socket_factory->AddSocketDataProvider(&data);
3967
3968 TestCompletionCallback callback;
3969
3970 scoped_ptr<HttpTransaction> trans(
3971 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3972
3973 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
3974 EXPECT_EQ(ERR_IO_PENDING, rv);
3975
3976 rv = callback.WaitForResult();
3977 EXPECT_EQ(expected_status, rv);
3978 }
3979
ConnectStatusHelper(const MockRead & status)3980 void HttpNetworkTransactionTest::ConnectStatusHelper(
3981 const MockRead& status) {
3982 ConnectStatusHelperWithExpectedStatus(
3983 status, ERR_TUNNEL_CONNECTION_FAILED);
3984 }
3985
TEST_P(HttpNetworkTransactionTest,ConnectStatus100)3986 TEST_P(HttpNetworkTransactionTest, ConnectStatus100) {
3987 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
3988 }
3989
TEST_P(HttpNetworkTransactionTest,ConnectStatus101)3990 TEST_P(HttpNetworkTransactionTest, ConnectStatus101) {
3991 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
3992 }
3993
TEST_P(HttpNetworkTransactionTest,ConnectStatus201)3994 TEST_P(HttpNetworkTransactionTest, ConnectStatus201) {
3995 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
3996 }
3997
TEST_P(HttpNetworkTransactionTest,ConnectStatus202)3998 TEST_P(HttpNetworkTransactionTest, ConnectStatus202) {
3999 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
4000 }
4001
TEST_P(HttpNetworkTransactionTest,ConnectStatus203)4002 TEST_P(HttpNetworkTransactionTest, ConnectStatus203) {
4003 ConnectStatusHelper(
4004 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
4005 }
4006
TEST_P(HttpNetworkTransactionTest,ConnectStatus204)4007 TEST_P(HttpNetworkTransactionTest, ConnectStatus204) {
4008 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
4009 }
4010
TEST_P(HttpNetworkTransactionTest,ConnectStatus205)4011 TEST_P(HttpNetworkTransactionTest, ConnectStatus205) {
4012 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
4013 }
4014
TEST_P(HttpNetworkTransactionTest,ConnectStatus206)4015 TEST_P(HttpNetworkTransactionTest, ConnectStatus206) {
4016 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
4017 }
4018
TEST_P(HttpNetworkTransactionTest,ConnectStatus300)4019 TEST_P(HttpNetworkTransactionTest, ConnectStatus300) {
4020 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
4021 }
4022
TEST_P(HttpNetworkTransactionTest,ConnectStatus301)4023 TEST_P(HttpNetworkTransactionTest, ConnectStatus301) {
4024 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
4025 }
4026
TEST_P(HttpNetworkTransactionTest,ConnectStatus302)4027 TEST_P(HttpNetworkTransactionTest, ConnectStatus302) {
4028 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
4029 }
4030
TEST_P(HttpNetworkTransactionTest,ConnectStatus303)4031 TEST_P(HttpNetworkTransactionTest, ConnectStatus303) {
4032 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
4033 }
4034
TEST_P(HttpNetworkTransactionTest,ConnectStatus304)4035 TEST_P(HttpNetworkTransactionTest, ConnectStatus304) {
4036 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
4037 }
4038
TEST_P(HttpNetworkTransactionTest,ConnectStatus305)4039 TEST_P(HttpNetworkTransactionTest, ConnectStatus305) {
4040 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
4041 }
4042
TEST_P(HttpNetworkTransactionTest,ConnectStatus306)4043 TEST_P(HttpNetworkTransactionTest, ConnectStatus306) {
4044 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
4045 }
4046
TEST_P(HttpNetworkTransactionTest,ConnectStatus307)4047 TEST_P(HttpNetworkTransactionTest, ConnectStatus307) {
4048 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
4049 }
4050
TEST_P(HttpNetworkTransactionTest,ConnectStatus308)4051 TEST_P(HttpNetworkTransactionTest, ConnectStatus308) {
4052 ConnectStatusHelper(MockRead("HTTP/1.1 308 Permanent Redirect\r\n"));
4053 }
4054
TEST_P(HttpNetworkTransactionTest,ConnectStatus400)4055 TEST_P(HttpNetworkTransactionTest, ConnectStatus400) {
4056 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
4057 }
4058
TEST_P(HttpNetworkTransactionTest,ConnectStatus401)4059 TEST_P(HttpNetworkTransactionTest, ConnectStatus401) {
4060 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
4061 }
4062
TEST_P(HttpNetworkTransactionTest,ConnectStatus402)4063 TEST_P(HttpNetworkTransactionTest, ConnectStatus402) {
4064 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
4065 }
4066
TEST_P(HttpNetworkTransactionTest,ConnectStatus403)4067 TEST_P(HttpNetworkTransactionTest, ConnectStatus403) {
4068 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
4069 }
4070
TEST_P(HttpNetworkTransactionTest,ConnectStatus404)4071 TEST_P(HttpNetworkTransactionTest, ConnectStatus404) {
4072 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
4073 }
4074
TEST_P(HttpNetworkTransactionTest,ConnectStatus405)4075 TEST_P(HttpNetworkTransactionTest, ConnectStatus405) {
4076 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
4077 }
4078
TEST_P(HttpNetworkTransactionTest,ConnectStatus406)4079 TEST_P(HttpNetworkTransactionTest, ConnectStatus406) {
4080 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
4081 }
4082
TEST_P(HttpNetworkTransactionTest,ConnectStatus407)4083 TEST_P(HttpNetworkTransactionTest, ConnectStatus407) {
4084 ConnectStatusHelperWithExpectedStatus(
4085 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4086 ERR_PROXY_AUTH_UNSUPPORTED);
4087 }
4088
TEST_P(HttpNetworkTransactionTest,ConnectStatus408)4089 TEST_P(HttpNetworkTransactionTest, ConnectStatus408) {
4090 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
4091 }
4092
TEST_P(HttpNetworkTransactionTest,ConnectStatus409)4093 TEST_P(HttpNetworkTransactionTest, ConnectStatus409) {
4094 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
4095 }
4096
TEST_P(HttpNetworkTransactionTest,ConnectStatus410)4097 TEST_P(HttpNetworkTransactionTest, ConnectStatus410) {
4098 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
4099 }
4100
TEST_P(HttpNetworkTransactionTest,ConnectStatus411)4101 TEST_P(HttpNetworkTransactionTest, ConnectStatus411) {
4102 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
4103 }
4104
TEST_P(HttpNetworkTransactionTest,ConnectStatus412)4105 TEST_P(HttpNetworkTransactionTest, ConnectStatus412) {
4106 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
4107 }
4108
TEST_P(HttpNetworkTransactionTest,ConnectStatus413)4109 TEST_P(HttpNetworkTransactionTest, ConnectStatus413) {
4110 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
4111 }
4112
TEST_P(HttpNetworkTransactionTest,ConnectStatus414)4113 TEST_P(HttpNetworkTransactionTest, ConnectStatus414) {
4114 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
4115 }
4116
TEST_P(HttpNetworkTransactionTest,ConnectStatus415)4117 TEST_P(HttpNetworkTransactionTest, ConnectStatus415) {
4118 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
4119 }
4120
TEST_P(HttpNetworkTransactionTest,ConnectStatus416)4121 TEST_P(HttpNetworkTransactionTest, ConnectStatus416) {
4122 ConnectStatusHelper(
4123 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
4124 }
4125
TEST_P(HttpNetworkTransactionTest,ConnectStatus417)4126 TEST_P(HttpNetworkTransactionTest, ConnectStatus417) {
4127 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
4128 }
4129
TEST_P(HttpNetworkTransactionTest,ConnectStatus500)4130 TEST_P(HttpNetworkTransactionTest, ConnectStatus500) {
4131 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
4132 }
4133
TEST_P(HttpNetworkTransactionTest,ConnectStatus501)4134 TEST_P(HttpNetworkTransactionTest, ConnectStatus501) {
4135 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
4136 }
4137
TEST_P(HttpNetworkTransactionTest,ConnectStatus502)4138 TEST_P(HttpNetworkTransactionTest, ConnectStatus502) {
4139 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
4140 }
4141
TEST_P(HttpNetworkTransactionTest,ConnectStatus503)4142 TEST_P(HttpNetworkTransactionTest, ConnectStatus503) {
4143 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
4144 }
4145
TEST_P(HttpNetworkTransactionTest,ConnectStatus504)4146 TEST_P(HttpNetworkTransactionTest, ConnectStatus504) {
4147 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
4148 }
4149
TEST_P(HttpNetworkTransactionTest,ConnectStatus505)4150 TEST_P(HttpNetworkTransactionTest, ConnectStatus505) {
4151 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
4152 }
4153
4154 // Test the flow when both the proxy server AND origin server require
4155 // authentication. Again, this uses basic auth for both since that is
4156 // the simplest to mock.
TEST_P(HttpNetworkTransactionTest,BasicAuthProxyThenServer)4157 TEST_P(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
4158 HttpRequestInfo request;
4159 request.method = "GET";
4160 request.url = GURL("http://www.google.com/");
4161 request.load_flags = 0;
4162
4163 // Configure against proxy server "myproxy:70".
4164 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
4165 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4166
4167 scoped_ptr<HttpTransaction> trans(
4168 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
4169
4170 MockWrite data_writes1[] = {
4171 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
4172 "Host: www.google.com\r\n"
4173 "Proxy-Connection: keep-alive\r\n\r\n"),
4174 };
4175
4176 MockRead data_reads1[] = {
4177 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
4178 // Give a couple authenticate options (only the middle one is actually
4179 // supported).
4180 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
4181 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4182 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
4183 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4184 // Large content-length -- won't matter, as connection will be reset.
4185 MockRead("Content-Length: 10000\r\n\r\n"),
4186 MockRead(SYNCHRONOUS, ERR_FAILED),
4187 };
4188
4189 // After calling trans->RestartWithAuth() the first time, this is the
4190 // request we should be issuing -- the final header line contains the
4191 // proxy's credentials.
4192 MockWrite data_writes2[] = {
4193 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
4194 "Host: www.google.com\r\n"
4195 "Proxy-Connection: keep-alive\r\n"
4196 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4197 };
4198
4199 // Now the proxy server lets the request pass through to origin server.
4200 // The origin server responds with a 401.
4201 MockRead data_reads2[] = {
4202 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4203 // Note: We are using the same realm-name as the proxy server. This is
4204 // completely valid, as realms are unique across hosts.
4205 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4206 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4207 MockRead("Content-Length: 2000\r\n\r\n"),
4208 MockRead(SYNCHRONOUS, ERR_FAILED), // Won't be reached.
4209 };
4210
4211 // After calling trans->RestartWithAuth() the second time, we should send
4212 // the credentials for both the proxy and origin server.
4213 MockWrite data_writes3[] = {
4214 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
4215 "Host: www.google.com\r\n"
4216 "Proxy-Connection: keep-alive\r\n"
4217 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
4218 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
4219 };
4220
4221 // Lastly we get the desired content.
4222 MockRead data_reads3[] = {
4223 MockRead("HTTP/1.0 200 OK\r\n"),
4224 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4225 MockRead("Content-Length: 100\r\n\r\n"),
4226 MockRead(SYNCHRONOUS, OK),
4227 };
4228
4229 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4230 data_writes1, arraysize(data_writes1));
4231 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4232 data_writes2, arraysize(data_writes2));
4233 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
4234 data_writes3, arraysize(data_writes3));
4235 session_deps_.socket_factory->AddSocketDataProvider(&data1);
4236 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4237 session_deps_.socket_factory->AddSocketDataProvider(&data3);
4238
4239 TestCompletionCallback callback1;
4240
4241 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
4242 EXPECT_EQ(ERR_IO_PENDING, rv);
4243
4244 rv = callback1.WaitForResult();
4245 EXPECT_EQ(OK, rv);
4246
4247 const HttpResponseInfo* response = trans->GetResponseInfo();
4248 ASSERT_TRUE(response != NULL);
4249 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
4250
4251 TestCompletionCallback callback2;
4252
4253 rv = trans->RestartWithAuth(
4254 AuthCredentials(kFoo, kBar), callback2.callback());
4255 EXPECT_EQ(ERR_IO_PENDING, rv);
4256
4257 rv = callback2.WaitForResult();
4258 EXPECT_EQ(OK, rv);
4259
4260 response = trans->GetResponseInfo();
4261 ASSERT_TRUE(response != NULL);
4262 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
4263
4264 TestCompletionCallback callback3;
4265
4266 rv = trans->RestartWithAuth(
4267 AuthCredentials(kFoo2, kBar2), callback3.callback());
4268 EXPECT_EQ(ERR_IO_PENDING, rv);
4269
4270 rv = callback3.WaitForResult();
4271 EXPECT_EQ(OK, rv);
4272
4273 response = trans->GetResponseInfo();
4274 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4275 EXPECT_EQ(100, response->headers->GetContentLength());
4276 }
4277
4278 // For the NTLM implementation using SSPI, we skip the NTLM tests since we
4279 // can't hook into its internals to cause it to generate predictable NTLM
4280 // authorization headers.
4281 #if defined(NTLM_PORTABLE)
4282 // The NTLM authentication unit tests were generated by capturing the HTTP
4283 // requests and responses using Fiddler 2 and inspecting the generated random
4284 // bytes in the debugger.
4285
4286 // Enter the correct password and authenticate successfully.
TEST_P(HttpNetworkTransactionTest,NTLMAuth1)4287 TEST_P(HttpNetworkTransactionTest, NTLMAuth1) {
4288 HttpRequestInfo request;
4289 request.method = "GET";
4290 request.url = GURL("http://172.22.68.17/kids/login.aspx");
4291
4292 // Ensure load is not disrupted by flags which suppress behaviour specific
4293 // to other auth schemes.
4294 request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
4295
4296 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom1,
4297 MockGetHostName);
4298 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4299
4300 MockWrite data_writes1[] = {
4301 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4302 "Host: 172.22.68.17\r\n"
4303 "Connection: keep-alive\r\n\r\n"),
4304 };
4305
4306 MockRead data_reads1[] = {
4307 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4308 // Negotiate and NTLM are often requested together. However, we only want
4309 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
4310 // the header that requests Negotiate for this test.
4311 MockRead("WWW-Authenticate: NTLM\r\n"),
4312 MockRead("Connection: close\r\n"),
4313 MockRead("Content-Length: 42\r\n"),
4314 MockRead("Content-Type: text/html\r\n\r\n"),
4315 // Missing content -- won't matter, as connection will be reset.
4316 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
4317 };
4318
4319 MockWrite data_writes2[] = {
4320 // After restarting with a null identity, this is the
4321 // request we should be issuing -- the final header line contains a Type
4322 // 1 message.
4323 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4324 "Host: 172.22.68.17\r\n"
4325 "Connection: keep-alive\r\n"
4326 "Authorization: NTLM "
4327 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4328
4329 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4330 // (the credentials for the origin server). The second request continues
4331 // on the same connection.
4332 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4333 "Host: 172.22.68.17\r\n"
4334 "Connection: keep-alive\r\n"
4335 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4336 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4337 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
4338 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
4339 "ahlhx5I=\r\n\r\n"),
4340 };
4341
4342 MockRead data_reads2[] = {
4343 // The origin server responds with a Type 2 message.
4344 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4345 MockRead("WWW-Authenticate: NTLM "
4346 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
4347 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4348 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4349 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4350 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4351 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4352 "BtAAAAAAA=\r\n"),
4353 MockRead("Content-Length: 42\r\n"),
4354 MockRead("Content-Type: text/html\r\n\r\n"),
4355 MockRead("You are not authorized to view this page\r\n"),
4356
4357 // Lastly we get the desired content.
4358 MockRead("HTTP/1.1 200 OK\r\n"),
4359 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
4360 MockRead("Content-Length: 13\r\n\r\n"),
4361 MockRead("Please Login\r\n"),
4362 MockRead(SYNCHRONOUS, OK),
4363 };
4364
4365 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4366 data_writes1, arraysize(data_writes1));
4367 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4368 data_writes2, arraysize(data_writes2));
4369 session_deps_.socket_factory->AddSocketDataProvider(&data1);
4370 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4371
4372 TestCompletionCallback callback1;
4373
4374 scoped_ptr<HttpTransaction> trans(
4375 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4376
4377 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
4378 EXPECT_EQ(ERR_IO_PENDING, rv);
4379
4380 rv = callback1.WaitForResult();
4381 EXPECT_EQ(OK, rv);
4382
4383 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4384
4385 const HttpResponseInfo* response = trans->GetResponseInfo();
4386 ASSERT_FALSE(response == NULL);
4387 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
4388
4389 TestCompletionCallback callback2;
4390
4391 rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kTestingNTLM),
4392 callback2.callback());
4393 EXPECT_EQ(ERR_IO_PENDING, rv);
4394
4395 rv = callback2.WaitForResult();
4396 EXPECT_EQ(OK, rv);
4397
4398 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
4399
4400 response = trans->GetResponseInfo();
4401 ASSERT_TRUE(response != NULL);
4402 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4403
4404 TestCompletionCallback callback3;
4405
4406 rv = trans->RestartWithAuth(AuthCredentials(), callback3.callback());
4407 EXPECT_EQ(ERR_IO_PENDING, rv);
4408
4409 rv = callback3.WaitForResult();
4410 EXPECT_EQ(OK, rv);
4411
4412 response = trans->GetResponseInfo();
4413 ASSERT_TRUE(response != NULL);
4414 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4415 EXPECT_EQ(13, response->headers->GetContentLength());
4416 }
4417
4418 // Enter a wrong password, and then the correct one.
TEST_P(HttpNetworkTransactionTest,NTLMAuth2)4419 TEST_P(HttpNetworkTransactionTest, NTLMAuth2) {
4420 HttpRequestInfo request;
4421 request.method = "GET";
4422 request.url = GURL("http://172.22.68.17/kids/login.aspx");
4423 request.load_flags = 0;
4424
4425 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom2,
4426 MockGetHostName);
4427 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4428
4429 MockWrite data_writes1[] = {
4430 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4431 "Host: 172.22.68.17\r\n"
4432 "Connection: keep-alive\r\n\r\n"),
4433 };
4434
4435 MockRead data_reads1[] = {
4436 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4437 // Negotiate and NTLM are often requested together. However, we only want
4438 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
4439 // the header that requests Negotiate for this test.
4440 MockRead("WWW-Authenticate: NTLM\r\n"),
4441 MockRead("Connection: close\r\n"),
4442 MockRead("Content-Length: 42\r\n"),
4443 MockRead("Content-Type: text/html\r\n\r\n"),
4444 // Missing content -- won't matter, as connection will be reset.
4445 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
4446 };
4447
4448 MockWrite data_writes2[] = {
4449 // After restarting with a null identity, this is the
4450 // request we should be issuing -- the final header line contains a Type
4451 // 1 message.
4452 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4453 "Host: 172.22.68.17\r\n"
4454 "Connection: keep-alive\r\n"
4455 "Authorization: NTLM "
4456 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4457
4458 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4459 // (the credentials for the origin server). The second request continues
4460 // on the same connection.
4461 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4462 "Host: 172.22.68.17\r\n"
4463 "Connection: keep-alive\r\n"
4464 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4465 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4466 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
4467 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
4468 "4Ww7b7E=\r\n\r\n"),
4469 };
4470
4471 MockRead data_reads2[] = {
4472 // The origin server responds with a Type 2 message.
4473 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4474 MockRead("WWW-Authenticate: NTLM "
4475 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
4476 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4477 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4478 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4479 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4480 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4481 "BtAAAAAAA=\r\n"),
4482 MockRead("Content-Length: 42\r\n"),
4483 MockRead("Content-Type: text/html\r\n\r\n"),
4484 MockRead("You are not authorized to view this page\r\n"),
4485
4486 // Wrong password.
4487 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4488 MockRead("WWW-Authenticate: NTLM\r\n"),
4489 MockRead("Connection: close\r\n"),
4490 MockRead("Content-Length: 42\r\n"),
4491 MockRead("Content-Type: text/html\r\n\r\n"),
4492 // Missing content -- won't matter, as connection will be reset.
4493 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
4494 };
4495
4496 MockWrite data_writes3[] = {
4497 // After restarting with a null identity, this is the
4498 // request we should be issuing -- the final header line contains a Type
4499 // 1 message.
4500 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4501 "Host: 172.22.68.17\r\n"
4502 "Connection: keep-alive\r\n"
4503 "Authorization: NTLM "
4504 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4505
4506 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4507 // (the credentials for the origin server). The second request continues
4508 // on the same connection.
4509 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4510 "Host: 172.22.68.17\r\n"
4511 "Connection: keep-alive\r\n"
4512 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4513 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4514 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
4515 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
4516 "+4MUm7c=\r\n\r\n"),
4517 };
4518
4519 MockRead data_reads3[] = {
4520 // The origin server responds with a Type 2 message.
4521 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4522 MockRead("WWW-Authenticate: NTLM "
4523 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
4524 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4525 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4526 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4527 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4528 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4529 "BtAAAAAAA=\r\n"),
4530 MockRead("Content-Length: 42\r\n"),
4531 MockRead("Content-Type: text/html\r\n\r\n"),
4532 MockRead("You are not authorized to view this page\r\n"),
4533
4534 // Lastly we get the desired content.
4535 MockRead("HTTP/1.1 200 OK\r\n"),
4536 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
4537 MockRead("Content-Length: 13\r\n\r\n"),
4538 MockRead("Please Login\r\n"),
4539 MockRead(SYNCHRONOUS, OK),
4540 };
4541
4542 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4543 data_writes1, arraysize(data_writes1));
4544 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4545 data_writes2, arraysize(data_writes2));
4546 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
4547 data_writes3, arraysize(data_writes3));
4548 session_deps_.socket_factory->AddSocketDataProvider(&data1);
4549 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4550 session_deps_.socket_factory->AddSocketDataProvider(&data3);
4551
4552 TestCompletionCallback callback1;
4553
4554 scoped_ptr<HttpTransaction> trans(
4555 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4556
4557 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
4558 EXPECT_EQ(ERR_IO_PENDING, rv);
4559
4560 rv = callback1.WaitForResult();
4561 EXPECT_EQ(OK, rv);
4562
4563 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4564
4565 const HttpResponseInfo* response = trans->GetResponseInfo();
4566 ASSERT_TRUE(response != NULL);
4567 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
4568
4569 TestCompletionCallback callback2;
4570
4571 // Enter the wrong password.
4572 rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kWrongPassword),
4573 callback2.callback());
4574 EXPECT_EQ(ERR_IO_PENDING, rv);
4575
4576 rv = callback2.WaitForResult();
4577 EXPECT_EQ(OK, rv);
4578
4579 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
4580 TestCompletionCallback callback3;
4581 rv = trans->RestartWithAuth(AuthCredentials(), callback3.callback());
4582 EXPECT_EQ(ERR_IO_PENDING, rv);
4583 rv = callback3.WaitForResult();
4584 EXPECT_EQ(OK, rv);
4585 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4586
4587 response = trans->GetResponseInfo();
4588 ASSERT_FALSE(response == NULL);
4589 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
4590
4591 TestCompletionCallback callback4;
4592
4593 // Now enter the right password.
4594 rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kTestingNTLM),
4595 callback4.callback());
4596 EXPECT_EQ(ERR_IO_PENDING, rv);
4597
4598 rv = callback4.WaitForResult();
4599 EXPECT_EQ(OK, rv);
4600
4601 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
4602
4603 TestCompletionCallback callback5;
4604
4605 // One more roundtrip
4606 rv = trans->RestartWithAuth(AuthCredentials(), callback5.callback());
4607 EXPECT_EQ(ERR_IO_PENDING, rv);
4608
4609 rv = callback5.WaitForResult();
4610 EXPECT_EQ(OK, rv);
4611
4612 response = trans->GetResponseInfo();
4613 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4614 EXPECT_EQ(13, response->headers->GetContentLength());
4615 }
4616 #endif // NTLM_PORTABLE
4617
4618 // Test reading a server response which has only headers, and no body.
4619 // After some maximum number of bytes is consumed, the transaction should
4620 // fail with ERR_RESPONSE_HEADERS_TOO_BIG.
TEST_P(HttpNetworkTransactionTest,LargeHeadersNoBody)4621 TEST_P(HttpNetworkTransactionTest, LargeHeadersNoBody) {
4622 HttpRequestInfo request;
4623 request.method = "GET";
4624 request.url = GURL("http://www.google.com/");
4625 request.load_flags = 0;
4626
4627 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4628 scoped_ptr<HttpTransaction> trans(
4629 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
4630
4631 // Respond with 300 kb of headers (we should fail after 256 kb).
4632 std::string large_headers_string;
4633 FillLargeHeadersString(&large_headers_string, 300 * 1024);
4634
4635 MockRead data_reads[] = {
4636 MockRead("HTTP/1.0 200 OK\r\n"),
4637 MockRead(ASYNC, large_headers_string.data(), large_headers_string.size()),
4638 MockRead("\r\nBODY"),
4639 MockRead(SYNCHRONOUS, OK),
4640 };
4641 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
4642 session_deps_.socket_factory->AddSocketDataProvider(&data);
4643
4644 TestCompletionCallback callback;
4645
4646 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
4647 EXPECT_EQ(ERR_IO_PENDING, rv);
4648
4649 rv = callback.WaitForResult();
4650 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG, rv);
4651
4652 const HttpResponseInfo* response = trans->GetResponseInfo();
4653 EXPECT_TRUE(response == NULL);
4654 }
4655
4656 // Make sure that we don't try to reuse a TCPClientSocket when failing to
4657 // establish tunnel.
4658 // http://code.google.com/p/chromium/issues/detail?id=3772
TEST_P(HttpNetworkTransactionTest,DontRecycleTransportSocketForSSLTunnel)4659 TEST_P(HttpNetworkTransactionTest,
4660 DontRecycleTransportSocketForSSLTunnel) {
4661 HttpRequestInfo request;
4662 request.method = "GET";
4663 request.url = GURL("https://www.google.com/");
4664 request.load_flags = 0;
4665
4666 // Configure against proxy server "myproxy:70".
4667 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
4668
4669 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4670
4671 scoped_ptr<HttpTransaction> trans(
4672 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4673
4674 // Since we have proxy, should try to establish tunnel.
4675 MockWrite data_writes1[] = {
4676 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4677 "Host: www.google.com\r\n"
4678 "Proxy-Connection: keep-alive\r\n\r\n"),
4679 };
4680
4681 // The proxy responds to the connect with a 404, using a persistent
4682 // connection. Usually a proxy would return 501 (not implemented),
4683 // or 200 (tunnel established).
4684 MockRead data_reads1[] = {
4685 MockRead("HTTP/1.1 404 Not Found\r\n"),
4686 MockRead("Content-Length: 10\r\n\r\n"),
4687 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
4688 };
4689
4690 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4691 data_writes1, arraysize(data_writes1));
4692 session_deps_.socket_factory->AddSocketDataProvider(&data1);
4693
4694 TestCompletionCallback callback1;
4695
4696 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
4697 EXPECT_EQ(ERR_IO_PENDING, rv);
4698
4699 rv = callback1.WaitForResult();
4700 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
4701
4702 const HttpResponseInfo* response = trans->GetResponseInfo();
4703 EXPECT_TRUE(response == NULL);
4704
4705 // Empty the current queue. This is necessary because idle sockets are
4706 // added to the connection pool asynchronously with a PostTask.
4707 base::MessageLoop::current()->RunUntilIdle();
4708
4709 // We now check to make sure the TCPClientSocket was not added back to
4710 // the pool.
4711 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
4712 trans.reset();
4713 base::MessageLoop::current()->RunUntilIdle();
4714 // Make sure that the socket didn't get recycled after calling the destructor.
4715 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
4716 }
4717
4718 // Make sure that we recycle a socket after reading all of the response body.
TEST_P(HttpNetworkTransactionTest,RecycleSocket)4719 TEST_P(HttpNetworkTransactionTest, RecycleSocket) {
4720 HttpRequestInfo request;
4721 request.method = "GET";
4722 request.url = GURL("http://www.google.com/");
4723 request.load_flags = 0;
4724
4725 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4726
4727 scoped_ptr<HttpTransaction> trans(
4728 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4729
4730 MockRead data_reads[] = {
4731 // A part of the response body is received with the response headers.
4732 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
4733 // The rest of the response body is received in two parts.
4734 MockRead("lo"),
4735 MockRead(" world"),
4736 MockRead("junk"), // Should not be read!!
4737 MockRead(SYNCHRONOUS, OK),
4738 };
4739
4740 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
4741 session_deps_.socket_factory->AddSocketDataProvider(&data);
4742
4743 TestCompletionCallback callback;
4744
4745 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
4746 EXPECT_EQ(ERR_IO_PENDING, rv);
4747
4748 rv = callback.WaitForResult();
4749 EXPECT_EQ(OK, rv);
4750
4751 const HttpResponseInfo* response = trans->GetResponseInfo();
4752 ASSERT_TRUE(response != NULL);
4753
4754 EXPECT_TRUE(response->headers.get() != NULL);
4755 std::string status_line = response->headers->GetStatusLine();
4756 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
4757
4758 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
4759
4760 std::string response_data;
4761 rv = ReadTransaction(trans.get(), &response_data);
4762 EXPECT_EQ(OK, rv);
4763 EXPECT_EQ("hello world", response_data);
4764
4765 // Empty the current queue. This is necessary because idle sockets are
4766 // added to the connection pool asynchronously with a PostTask.
4767 base::MessageLoop::current()->RunUntilIdle();
4768
4769 // We now check to make sure the socket was added back to the pool.
4770 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
4771 }
4772
4773 // Make sure that we recycle a SSL socket after reading all of the response
4774 // body.
TEST_P(HttpNetworkTransactionTest,RecycleSSLSocket)4775 TEST_P(HttpNetworkTransactionTest, RecycleSSLSocket) {
4776 HttpRequestInfo request;
4777 request.method = "GET";
4778 request.url = GURL("https://www.google.com/");
4779 request.load_flags = 0;
4780
4781 MockWrite data_writes[] = {
4782 MockWrite("GET / HTTP/1.1\r\n"
4783 "Host: www.google.com\r\n"
4784 "Connection: keep-alive\r\n\r\n"),
4785 };
4786
4787 MockRead data_reads[] = {
4788 MockRead("HTTP/1.1 200 OK\r\n"),
4789 MockRead("Content-Length: 11\r\n\r\n"),
4790 MockRead("hello world"),
4791 MockRead(SYNCHRONOUS, OK),
4792 };
4793
4794 SSLSocketDataProvider ssl(ASYNC, OK);
4795 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
4796
4797 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4798 data_writes, arraysize(data_writes));
4799 session_deps_.socket_factory->AddSocketDataProvider(&data);
4800
4801 TestCompletionCallback callback;
4802
4803 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4804 scoped_ptr<HttpTransaction> trans(
4805 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4806
4807 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
4808
4809 EXPECT_EQ(ERR_IO_PENDING, rv);
4810 EXPECT_EQ(OK, callback.WaitForResult());
4811
4812 const HttpResponseInfo* response = trans->GetResponseInfo();
4813 ASSERT_TRUE(response != NULL);
4814 ASSERT_TRUE(response->headers.get() != NULL);
4815 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4816
4817 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
4818
4819 std::string response_data;
4820 rv = ReadTransaction(trans.get(), &response_data);
4821 EXPECT_EQ(OK, rv);
4822 EXPECT_EQ("hello world", response_data);
4823
4824 // Empty the current queue. This is necessary because idle sockets are
4825 // added to the connection pool asynchronously with a PostTask.
4826 base::MessageLoop::current()->RunUntilIdle();
4827
4828 // We now check to make sure the socket was added back to the pool.
4829 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
4830 }
4831
4832 // Grab a SSL socket, use it, and put it back into the pool. Then, reuse it
4833 // from the pool and make sure that we recover okay.
TEST_P(HttpNetworkTransactionTest,RecycleDeadSSLSocket)4834 TEST_P(HttpNetworkTransactionTest, RecycleDeadSSLSocket) {
4835 HttpRequestInfo request;
4836 request.method = "GET";
4837 request.url = GURL("https://www.google.com/");
4838 request.load_flags = 0;
4839
4840 MockWrite data_writes[] = {
4841 MockWrite("GET / HTTP/1.1\r\n"
4842 "Host: www.google.com\r\n"
4843 "Connection: keep-alive\r\n\r\n"),
4844 MockWrite("GET / HTTP/1.1\r\n"
4845 "Host: www.google.com\r\n"
4846 "Connection: keep-alive\r\n\r\n"),
4847 };
4848
4849 MockRead data_reads[] = {
4850 MockRead("HTTP/1.1 200 OK\r\n"),
4851 MockRead("Content-Length: 11\r\n\r\n"),
4852 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
4853 MockRead("hello world"),
4854 MockRead(ASYNC, 0, 0) // EOF
4855 };
4856
4857 SSLSocketDataProvider ssl(ASYNC, OK);
4858 SSLSocketDataProvider ssl2(ASYNC, OK);
4859 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
4860 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
4861
4862 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4863 data_writes, arraysize(data_writes));
4864 StaticSocketDataProvider data2(data_reads, arraysize(data_reads),
4865 data_writes, arraysize(data_writes));
4866 session_deps_.socket_factory->AddSocketDataProvider(&data);
4867 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4868
4869 TestCompletionCallback callback;
4870
4871 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4872 scoped_ptr<HttpTransaction> trans(
4873 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4874
4875 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
4876
4877 EXPECT_EQ(ERR_IO_PENDING, rv);
4878 EXPECT_EQ(OK, callback.WaitForResult());
4879
4880 const HttpResponseInfo* response = trans->GetResponseInfo();
4881 ASSERT_TRUE(response != NULL);
4882 ASSERT_TRUE(response->headers.get() != NULL);
4883 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4884
4885 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
4886
4887 std::string response_data;
4888 rv = ReadTransaction(trans.get(), &response_data);
4889 EXPECT_EQ(OK, rv);
4890 EXPECT_EQ("hello world", response_data);
4891
4892 // Empty the current queue. This is necessary because idle sockets are
4893 // added to the connection pool asynchronously with a PostTask.
4894 base::MessageLoop::current()->RunUntilIdle();
4895
4896 // We now check to make sure the socket was added back to the pool.
4897 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
4898
4899 // Now start the second transaction, which should reuse the previous socket.
4900
4901 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4902
4903 rv = trans->Start(&request, callback.callback(), BoundNetLog());
4904
4905 EXPECT_EQ(ERR_IO_PENDING, rv);
4906 EXPECT_EQ(OK, callback.WaitForResult());
4907
4908 response = trans->GetResponseInfo();
4909 ASSERT_TRUE(response != NULL);
4910 ASSERT_TRUE(response->headers.get() != NULL);
4911 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4912
4913 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
4914
4915 rv = ReadTransaction(trans.get(), &response_data);
4916 EXPECT_EQ(OK, rv);
4917 EXPECT_EQ("hello world", response_data);
4918
4919 // Empty the current queue. This is necessary because idle sockets are
4920 // added to the connection pool asynchronously with a PostTask.
4921 base::MessageLoop::current()->RunUntilIdle();
4922
4923 // We now check to make sure the socket was added back to the pool.
4924 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
4925 }
4926
4927 // Make sure that we recycle a socket after a zero-length response.
4928 // http://crbug.com/9880
TEST_P(HttpNetworkTransactionTest,RecycleSocketAfterZeroContentLength)4929 TEST_P(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
4930 HttpRequestInfo request;
4931 request.method = "GET";
4932 request.url = GURL("http://www.google.com/csi?v=3&s=web&action=&"
4933 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
4934 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
4935 "rt=prt.2642,ol.2649,xjs.2951");
4936 request.load_flags = 0;
4937
4938 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4939
4940 scoped_ptr<HttpTransaction> trans(
4941 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4942
4943 MockRead data_reads[] = {
4944 MockRead("HTTP/1.1 204 No Content\r\n"
4945 "Content-Length: 0\r\n"
4946 "Content-Type: text/html\r\n\r\n"),
4947 MockRead("junk"), // Should not be read!!
4948 MockRead(SYNCHRONOUS, OK),
4949 };
4950
4951 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
4952 session_deps_.socket_factory->AddSocketDataProvider(&data);
4953
4954 TestCompletionCallback callback;
4955
4956 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
4957 EXPECT_EQ(ERR_IO_PENDING, rv);
4958
4959 rv = callback.WaitForResult();
4960 EXPECT_EQ(OK, rv);
4961
4962 const HttpResponseInfo* response = trans->GetResponseInfo();
4963 ASSERT_TRUE(response != NULL);
4964
4965 EXPECT_TRUE(response->headers.get() != NULL);
4966 std::string status_line = response->headers->GetStatusLine();
4967 EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
4968
4969 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
4970
4971 std::string response_data;
4972 rv = ReadTransaction(trans.get(), &response_data);
4973 EXPECT_EQ(OK, rv);
4974 EXPECT_EQ("", response_data);
4975
4976 // Empty the current queue. This is necessary because idle sockets are
4977 // added to the connection pool asynchronously with a PostTask.
4978 base::MessageLoop::current()->RunUntilIdle();
4979
4980 // We now check to make sure the socket was added back to the pool.
4981 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
4982 }
4983
TEST_P(HttpNetworkTransactionTest,ResendRequestOnWriteBodyError)4984 TEST_P(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
4985 ScopedVector<UploadElementReader> element_readers;
4986 element_readers.push_back(new UploadBytesElementReader("foo", 3));
4987 UploadDataStream upload_data_stream(element_readers.Pass(), 0);
4988
4989 HttpRequestInfo request[2];
4990 // Transaction 1: a GET request that succeeds. The socket is recycled
4991 // after use.
4992 request[0].method = "GET";
4993 request[0].url = GURL("http://www.google.com/");
4994 request[0].load_flags = 0;
4995 // Transaction 2: a POST request. Reuses the socket kept alive from
4996 // transaction 1. The first attempts fails when writing the POST data.
4997 // This causes the transaction to retry with a new socket. The second
4998 // attempt succeeds.
4999 request[1].method = "POST";
5000 request[1].url = GURL("http://www.google.com/login.cgi");
5001 request[1].upload_data_stream = &upload_data_stream;
5002 request[1].load_flags = 0;
5003
5004 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5005
5006 // The first socket is used for transaction 1 and the first attempt of
5007 // transaction 2.
5008
5009 // The response of transaction 1.
5010 MockRead data_reads1[] = {
5011 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
5012 MockRead("hello world"),
5013 MockRead(SYNCHRONOUS, OK),
5014 };
5015 // The mock write results of transaction 1 and the first attempt of
5016 // transaction 2.
5017 MockWrite data_writes1[] = {
5018 MockWrite(SYNCHRONOUS, 64), // GET
5019 MockWrite(SYNCHRONOUS, 93), // POST
5020 MockWrite(SYNCHRONOUS, ERR_CONNECTION_ABORTED), // POST data
5021 };
5022 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5023 data_writes1, arraysize(data_writes1));
5024
5025 // The second socket is used for the second attempt of transaction 2.
5026
5027 // The response of transaction 2.
5028 MockRead data_reads2[] = {
5029 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
5030 MockRead("welcome"),
5031 MockRead(SYNCHRONOUS, OK),
5032 };
5033 // The mock write results of the second attempt of transaction 2.
5034 MockWrite data_writes2[] = {
5035 MockWrite(SYNCHRONOUS, 93), // POST
5036 MockWrite(SYNCHRONOUS, 3), // POST data
5037 };
5038 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5039 data_writes2, arraysize(data_writes2));
5040
5041 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5042 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5043
5044 const char* kExpectedResponseData[] = {
5045 "hello world", "welcome"
5046 };
5047
5048 for (int i = 0; i < 2; ++i) {
5049 scoped_ptr<HttpTransaction> trans(
5050 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5051
5052 TestCompletionCallback callback;
5053
5054 int rv = trans->Start(&request[i], callback.callback(), BoundNetLog());
5055 EXPECT_EQ(ERR_IO_PENDING, rv);
5056
5057 rv = callback.WaitForResult();
5058 EXPECT_EQ(OK, rv);
5059
5060 const HttpResponseInfo* response = trans->GetResponseInfo();
5061 ASSERT_TRUE(response != NULL);
5062
5063 EXPECT_TRUE(response->headers.get() != NULL);
5064 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5065
5066 std::string response_data;
5067 rv = ReadTransaction(trans.get(), &response_data);
5068 EXPECT_EQ(OK, rv);
5069 EXPECT_EQ(kExpectedResponseData[i], response_data);
5070 }
5071 }
5072
5073 // Test the request-challenge-retry sequence for basic auth when there is
5074 // an identity in the URL. The request should be sent as normal, but when
5075 // it fails the identity from the URL is used to answer the challenge.
TEST_P(HttpNetworkTransactionTest,AuthIdentityInURL)5076 TEST_P(HttpNetworkTransactionTest, AuthIdentityInURL) {
5077 HttpRequestInfo request;
5078 request.method = "GET";
5079 request.url = GURL("http://foo:b@r@www.google.com/");
5080 request.load_flags = LOAD_NORMAL;
5081
5082 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5083 scoped_ptr<HttpTransaction> trans(
5084 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
5085
5086 // The password contains an escaped character -- for this test to pass it
5087 // will need to be unescaped by HttpNetworkTransaction.
5088 EXPECT_EQ("b%40r", request.url.password());
5089
5090 MockWrite data_writes1[] = {
5091 MockWrite("GET / HTTP/1.1\r\n"
5092 "Host: www.google.com\r\n"
5093 "Connection: keep-alive\r\n\r\n"),
5094 };
5095
5096 MockRead data_reads1[] = {
5097 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5098 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5099 MockRead("Content-Length: 10\r\n\r\n"),
5100 MockRead(SYNCHRONOUS, ERR_FAILED),
5101 };
5102
5103 // After the challenge above, the transaction will be restarted using the
5104 // identity from the url (foo, b@r) to answer the challenge.
5105 MockWrite data_writes2[] = {
5106 MockWrite("GET / HTTP/1.1\r\n"
5107 "Host: www.google.com\r\n"
5108 "Connection: keep-alive\r\n"
5109 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
5110 };
5111
5112 MockRead data_reads2[] = {
5113 MockRead("HTTP/1.0 200 OK\r\n"),
5114 MockRead("Content-Length: 100\r\n\r\n"),
5115 MockRead(SYNCHRONOUS, OK),
5116 };
5117
5118 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5119 data_writes1, arraysize(data_writes1));
5120 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5121 data_writes2, arraysize(data_writes2));
5122 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5123 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5124
5125 TestCompletionCallback callback1;
5126 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5127 EXPECT_EQ(ERR_IO_PENDING, rv);
5128 rv = callback1.WaitForResult();
5129 EXPECT_EQ(OK, rv);
5130 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
5131
5132 TestCompletionCallback callback2;
5133 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
5134 EXPECT_EQ(ERR_IO_PENDING, rv);
5135 rv = callback2.WaitForResult();
5136 EXPECT_EQ(OK, rv);
5137 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5138
5139 const HttpResponseInfo* response = trans->GetResponseInfo();
5140 ASSERT_TRUE(response != NULL);
5141
5142 // There is no challenge info, since the identity in URL worked.
5143 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5144
5145 EXPECT_EQ(100, response->headers->GetContentLength());
5146
5147 // Empty the current queue.
5148 base::MessageLoop::current()->RunUntilIdle();
5149 }
5150
5151 // Test the request-challenge-retry sequence for basic auth when there is an
5152 // incorrect identity in the URL. The identity from the URL should be used only
5153 // once.
TEST_P(HttpNetworkTransactionTest,WrongAuthIdentityInURL)5154 TEST_P(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
5155 HttpRequestInfo request;
5156 request.method = "GET";
5157 // Note: the URL has a username:password in it. The password "baz" is
5158 // wrong (should be "bar").
5159 request.url = GURL("http://foo:baz@www.google.com/");
5160
5161 request.load_flags = LOAD_NORMAL;
5162
5163 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5164 scoped_ptr<HttpTransaction> trans(
5165 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
5166
5167 MockWrite data_writes1[] = {
5168 MockWrite("GET / HTTP/1.1\r\n"
5169 "Host: www.google.com\r\n"
5170 "Connection: keep-alive\r\n\r\n"),
5171 };
5172
5173 MockRead data_reads1[] = {
5174 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5175 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5176 MockRead("Content-Length: 10\r\n\r\n"),
5177 MockRead(SYNCHRONOUS, ERR_FAILED),
5178 };
5179
5180 // After the challenge above, the transaction will be restarted using the
5181 // identity from the url (foo, baz) to answer the challenge.
5182 MockWrite data_writes2[] = {
5183 MockWrite("GET / HTTP/1.1\r\n"
5184 "Host: www.google.com\r\n"
5185 "Connection: keep-alive\r\n"
5186 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
5187 };
5188
5189 MockRead data_reads2[] = {
5190 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5191 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5192 MockRead("Content-Length: 10\r\n\r\n"),
5193 MockRead(SYNCHRONOUS, ERR_FAILED),
5194 };
5195
5196 // After the challenge above, the transaction will be restarted using the
5197 // identity supplied by the user (foo, bar) to answer the challenge.
5198 MockWrite data_writes3[] = {
5199 MockWrite("GET / HTTP/1.1\r\n"
5200 "Host: www.google.com\r\n"
5201 "Connection: keep-alive\r\n"
5202 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5203 };
5204
5205 MockRead data_reads3[] = {
5206 MockRead("HTTP/1.0 200 OK\r\n"),
5207 MockRead("Content-Length: 100\r\n\r\n"),
5208 MockRead(SYNCHRONOUS, OK),
5209 };
5210
5211 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5212 data_writes1, arraysize(data_writes1));
5213 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5214 data_writes2, arraysize(data_writes2));
5215 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
5216 data_writes3, arraysize(data_writes3));
5217 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5218 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5219 session_deps_.socket_factory->AddSocketDataProvider(&data3);
5220
5221 TestCompletionCallback callback1;
5222
5223 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5224 EXPECT_EQ(ERR_IO_PENDING, rv);
5225
5226 rv = callback1.WaitForResult();
5227 EXPECT_EQ(OK, rv);
5228
5229 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
5230 TestCompletionCallback callback2;
5231 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
5232 EXPECT_EQ(ERR_IO_PENDING, rv);
5233 rv = callback2.WaitForResult();
5234 EXPECT_EQ(OK, rv);
5235 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5236
5237 const HttpResponseInfo* response = trans->GetResponseInfo();
5238 ASSERT_TRUE(response != NULL);
5239 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
5240
5241 TestCompletionCallback callback3;
5242 rv = trans->RestartWithAuth(
5243 AuthCredentials(kFoo, kBar), callback3.callback());
5244 EXPECT_EQ(ERR_IO_PENDING, rv);
5245 rv = callback3.WaitForResult();
5246 EXPECT_EQ(OK, rv);
5247 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5248
5249 response = trans->GetResponseInfo();
5250 ASSERT_TRUE(response != NULL);
5251
5252 // There is no challenge info, since the identity worked.
5253 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5254
5255 EXPECT_EQ(100, response->headers->GetContentLength());
5256
5257 // Empty the current queue.
5258 base::MessageLoop::current()->RunUntilIdle();
5259 }
5260
5261
5262 // Test the request-challenge-retry sequence for basic auth when there is a
5263 // correct identity in the URL, but its use is being suppressed. The identity
5264 // from the URL should never be used.
TEST_P(HttpNetworkTransactionTest,AuthIdentityInURLSuppressed)5265 TEST_P(HttpNetworkTransactionTest, AuthIdentityInURLSuppressed) {
5266 HttpRequestInfo request;
5267 request.method = "GET";
5268 request.url = GURL("http://foo:bar@www.google.com/");
5269 request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
5270
5271 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5272 scoped_ptr<HttpTransaction> trans(
5273 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
5274
5275 MockWrite data_writes1[] = {
5276 MockWrite("GET / HTTP/1.1\r\n"
5277 "Host: www.google.com\r\n"
5278 "Connection: keep-alive\r\n\r\n"),
5279 };
5280
5281 MockRead data_reads1[] = {
5282 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5283 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5284 MockRead("Content-Length: 10\r\n\r\n"),
5285 MockRead(SYNCHRONOUS, ERR_FAILED),
5286 };
5287
5288 // After the challenge above, the transaction will be restarted using the
5289 // identity supplied by the user, not the one in the URL, to answer the
5290 // challenge.
5291 MockWrite data_writes3[] = {
5292 MockWrite("GET / HTTP/1.1\r\n"
5293 "Host: www.google.com\r\n"
5294 "Connection: keep-alive\r\n"
5295 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5296 };
5297
5298 MockRead data_reads3[] = {
5299 MockRead("HTTP/1.0 200 OK\r\n"),
5300 MockRead("Content-Length: 100\r\n\r\n"),
5301 MockRead(SYNCHRONOUS, OK),
5302 };
5303
5304 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5305 data_writes1, arraysize(data_writes1));
5306 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
5307 data_writes3, arraysize(data_writes3));
5308 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5309 session_deps_.socket_factory->AddSocketDataProvider(&data3);
5310
5311 TestCompletionCallback callback1;
5312 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5313 EXPECT_EQ(ERR_IO_PENDING, rv);
5314 rv = callback1.WaitForResult();
5315 EXPECT_EQ(OK, rv);
5316 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5317
5318 const HttpResponseInfo* response = trans->GetResponseInfo();
5319 ASSERT_TRUE(response != NULL);
5320 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
5321
5322 TestCompletionCallback callback3;
5323 rv = trans->RestartWithAuth(
5324 AuthCredentials(kFoo, kBar), callback3.callback());
5325 EXPECT_EQ(ERR_IO_PENDING, rv);
5326 rv = callback3.WaitForResult();
5327 EXPECT_EQ(OK, rv);
5328 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5329
5330 response = trans->GetResponseInfo();
5331 ASSERT_TRUE(response != NULL);
5332
5333 // There is no challenge info, since the identity worked.
5334 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5335 EXPECT_EQ(100, response->headers->GetContentLength());
5336
5337 // Empty the current queue.
5338 base::MessageLoop::current()->RunUntilIdle();
5339 }
5340
5341 // Test that previously tried username/passwords for a realm get re-used.
TEST_P(HttpNetworkTransactionTest,BasicAuthCacheAndPreauth)5342 TEST_P(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
5343 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5344
5345 // Transaction 1: authenticate (foo, bar) on MyRealm1
5346 {
5347 HttpRequestInfo request;
5348 request.method = "GET";
5349 request.url = GURL("http://www.google.com/x/y/z");
5350 request.load_flags = 0;
5351
5352 scoped_ptr<HttpTransaction> trans(
5353 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5354
5355 MockWrite data_writes1[] = {
5356 MockWrite("GET /x/y/z HTTP/1.1\r\n"
5357 "Host: www.google.com\r\n"
5358 "Connection: keep-alive\r\n\r\n"),
5359 };
5360
5361 MockRead data_reads1[] = {
5362 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5363 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5364 MockRead("Content-Length: 10000\r\n\r\n"),
5365 MockRead(SYNCHRONOUS, ERR_FAILED),
5366 };
5367
5368 // Resend with authorization (username=foo, password=bar)
5369 MockWrite data_writes2[] = {
5370 MockWrite("GET /x/y/z HTTP/1.1\r\n"
5371 "Host: www.google.com\r\n"
5372 "Connection: keep-alive\r\n"
5373 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5374 };
5375
5376 // Sever accepts the authorization.
5377 MockRead data_reads2[] = {
5378 MockRead("HTTP/1.0 200 OK\r\n"),
5379 MockRead("Content-Length: 100\r\n\r\n"),
5380 MockRead(SYNCHRONOUS, OK),
5381 };
5382
5383 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5384 data_writes1, arraysize(data_writes1));
5385 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5386 data_writes2, arraysize(data_writes2));
5387 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5388 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5389
5390 TestCompletionCallback callback1;
5391
5392 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5393 EXPECT_EQ(ERR_IO_PENDING, rv);
5394
5395 rv = callback1.WaitForResult();
5396 EXPECT_EQ(OK, rv);
5397
5398 const HttpResponseInfo* response = trans->GetResponseInfo();
5399 ASSERT_TRUE(response != NULL);
5400 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
5401
5402 TestCompletionCallback callback2;
5403
5404 rv = trans->RestartWithAuth(
5405 AuthCredentials(kFoo, kBar), callback2.callback());
5406 EXPECT_EQ(ERR_IO_PENDING, rv);
5407
5408 rv = callback2.WaitForResult();
5409 EXPECT_EQ(OK, rv);
5410
5411 response = trans->GetResponseInfo();
5412 ASSERT_TRUE(response != NULL);
5413 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5414 EXPECT_EQ(100, response->headers->GetContentLength());
5415 }
5416
5417 // ------------------------------------------------------------------------
5418
5419 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
5420 {
5421 HttpRequestInfo request;
5422 request.method = "GET";
5423 // Note that Transaction 1 was at /x/y/z, so this is in the same
5424 // protection space as MyRealm1.
5425 request.url = GURL("http://www.google.com/x/y/a/b");
5426 request.load_flags = 0;
5427
5428 scoped_ptr<HttpTransaction> trans(
5429 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5430
5431 MockWrite data_writes1[] = {
5432 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
5433 "Host: www.google.com\r\n"
5434 "Connection: keep-alive\r\n"
5435 // Send preemptive authorization for MyRealm1
5436 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5437 };
5438
5439 // The server didn't like the preemptive authorization, and
5440 // challenges us for a different realm (MyRealm2).
5441 MockRead data_reads1[] = {
5442 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5443 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
5444 MockRead("Content-Length: 10000\r\n\r\n"),
5445 MockRead(SYNCHRONOUS, ERR_FAILED),
5446 };
5447
5448 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
5449 MockWrite data_writes2[] = {
5450 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
5451 "Host: www.google.com\r\n"
5452 "Connection: keep-alive\r\n"
5453 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
5454 };
5455
5456 // Sever accepts the authorization.
5457 MockRead data_reads2[] = {
5458 MockRead("HTTP/1.0 200 OK\r\n"),
5459 MockRead("Content-Length: 100\r\n\r\n"),
5460 MockRead(SYNCHRONOUS, OK),
5461 };
5462
5463 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5464 data_writes1, arraysize(data_writes1));
5465 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5466 data_writes2, arraysize(data_writes2));
5467 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5468 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5469
5470 TestCompletionCallback callback1;
5471
5472 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5473 EXPECT_EQ(ERR_IO_PENDING, rv);
5474
5475 rv = callback1.WaitForResult();
5476 EXPECT_EQ(OK, rv);
5477
5478 const HttpResponseInfo* response = trans->GetResponseInfo();
5479 ASSERT_TRUE(response != NULL);
5480 ASSERT_TRUE(response->auth_challenge.get());
5481 EXPECT_FALSE(response->auth_challenge->is_proxy);
5482 EXPECT_EQ("www.google.com:80",
5483 response->auth_challenge->challenger.ToString());
5484 EXPECT_EQ("MyRealm2", response->auth_challenge->realm);
5485 EXPECT_EQ("basic", response->auth_challenge->scheme);
5486
5487 TestCompletionCallback callback2;
5488
5489 rv = trans->RestartWithAuth(
5490 AuthCredentials(kFoo2, kBar2), callback2.callback());
5491 EXPECT_EQ(ERR_IO_PENDING, rv);
5492
5493 rv = callback2.WaitForResult();
5494 EXPECT_EQ(OK, rv);
5495
5496 response = trans->GetResponseInfo();
5497 ASSERT_TRUE(response != NULL);
5498 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5499 EXPECT_EQ(100, response->headers->GetContentLength());
5500 }
5501
5502 // ------------------------------------------------------------------------
5503
5504 // Transaction 3: Resend a request in MyRealm's protection space --
5505 // succeed with preemptive authorization.
5506 {
5507 HttpRequestInfo request;
5508 request.method = "GET";
5509 request.url = GURL("http://www.google.com/x/y/z2");
5510 request.load_flags = 0;
5511
5512 scoped_ptr<HttpTransaction> trans(
5513 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5514
5515 MockWrite data_writes1[] = {
5516 MockWrite("GET /x/y/z2 HTTP/1.1\r\n"
5517 "Host: www.google.com\r\n"
5518 "Connection: keep-alive\r\n"
5519 // The authorization for MyRealm1 gets sent preemptively
5520 // (since the url is in the same protection space)
5521 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5522 };
5523
5524 // Sever accepts the preemptive authorization
5525 MockRead data_reads1[] = {
5526 MockRead("HTTP/1.0 200 OK\r\n"),
5527 MockRead("Content-Length: 100\r\n\r\n"),
5528 MockRead(SYNCHRONOUS, OK),
5529 };
5530
5531 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5532 data_writes1, arraysize(data_writes1));
5533 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5534
5535 TestCompletionCallback callback1;
5536
5537 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5538 EXPECT_EQ(ERR_IO_PENDING, rv);
5539
5540 rv = callback1.WaitForResult();
5541 EXPECT_EQ(OK, rv);
5542
5543 const HttpResponseInfo* response = trans->GetResponseInfo();
5544 ASSERT_TRUE(response != NULL);
5545
5546 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5547 EXPECT_EQ(100, response->headers->GetContentLength());
5548 }
5549
5550 // ------------------------------------------------------------------------
5551
5552 // Transaction 4: request another URL in MyRealm (however the
5553 // url is not known to belong to the protection space, so no pre-auth).
5554 {
5555 HttpRequestInfo request;
5556 request.method = "GET";
5557 request.url = GURL("http://www.google.com/x/1");
5558 request.load_flags = 0;
5559
5560 scoped_ptr<HttpTransaction> trans(
5561 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5562
5563 MockWrite data_writes1[] = {
5564 MockWrite("GET /x/1 HTTP/1.1\r\n"
5565 "Host: www.google.com\r\n"
5566 "Connection: keep-alive\r\n\r\n"),
5567 };
5568
5569 MockRead data_reads1[] = {
5570 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5571 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5572 MockRead("Content-Length: 10000\r\n\r\n"),
5573 MockRead(SYNCHRONOUS, ERR_FAILED),
5574 };
5575
5576 // Resend with authorization from MyRealm's cache.
5577 MockWrite data_writes2[] = {
5578 MockWrite("GET /x/1 HTTP/1.1\r\n"
5579 "Host: www.google.com\r\n"
5580 "Connection: keep-alive\r\n"
5581 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5582 };
5583
5584 // Sever accepts the authorization.
5585 MockRead data_reads2[] = {
5586 MockRead("HTTP/1.0 200 OK\r\n"),
5587 MockRead("Content-Length: 100\r\n\r\n"),
5588 MockRead(SYNCHRONOUS, OK),
5589 };
5590
5591 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5592 data_writes1, arraysize(data_writes1));
5593 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5594 data_writes2, arraysize(data_writes2));
5595 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5596 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5597
5598 TestCompletionCallback callback1;
5599
5600 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5601 EXPECT_EQ(ERR_IO_PENDING, rv);
5602
5603 rv = callback1.WaitForResult();
5604 EXPECT_EQ(OK, rv);
5605
5606 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
5607 TestCompletionCallback callback2;
5608 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
5609 EXPECT_EQ(ERR_IO_PENDING, rv);
5610 rv = callback2.WaitForResult();
5611 EXPECT_EQ(OK, rv);
5612 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5613
5614 const HttpResponseInfo* response = trans->GetResponseInfo();
5615 ASSERT_TRUE(response != NULL);
5616 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5617 EXPECT_EQ(100, response->headers->GetContentLength());
5618 }
5619
5620 // ------------------------------------------------------------------------
5621
5622 // Transaction 5: request a URL in MyRealm, but the server rejects the
5623 // cached identity. Should invalidate and re-prompt.
5624 {
5625 HttpRequestInfo request;
5626 request.method = "GET";
5627 request.url = GURL("http://www.google.com/p/q/t");
5628 request.load_flags = 0;
5629
5630 scoped_ptr<HttpTransaction> trans(
5631 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5632
5633 MockWrite data_writes1[] = {
5634 MockWrite("GET /p/q/t HTTP/1.1\r\n"
5635 "Host: www.google.com\r\n"
5636 "Connection: keep-alive\r\n\r\n"),
5637 };
5638
5639 MockRead data_reads1[] = {
5640 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5641 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5642 MockRead("Content-Length: 10000\r\n\r\n"),
5643 MockRead(SYNCHRONOUS, ERR_FAILED),
5644 };
5645
5646 // Resend with authorization from cache for MyRealm.
5647 MockWrite data_writes2[] = {
5648 MockWrite("GET /p/q/t HTTP/1.1\r\n"
5649 "Host: www.google.com\r\n"
5650 "Connection: keep-alive\r\n"
5651 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5652 };
5653
5654 // Sever rejects the authorization.
5655 MockRead data_reads2[] = {
5656 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5657 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5658 MockRead("Content-Length: 10000\r\n\r\n"),
5659 MockRead(SYNCHRONOUS, ERR_FAILED),
5660 };
5661
5662 // At this point we should prompt for new credentials for MyRealm.
5663 // Restart with username=foo3, password=foo4.
5664 MockWrite data_writes3[] = {
5665 MockWrite("GET /p/q/t HTTP/1.1\r\n"
5666 "Host: www.google.com\r\n"
5667 "Connection: keep-alive\r\n"
5668 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
5669 };
5670
5671 // Sever accepts the authorization.
5672 MockRead data_reads3[] = {
5673 MockRead("HTTP/1.0 200 OK\r\n"),
5674 MockRead("Content-Length: 100\r\n\r\n"),
5675 MockRead(SYNCHRONOUS, OK),
5676 };
5677
5678 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5679 data_writes1, arraysize(data_writes1));
5680 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5681 data_writes2, arraysize(data_writes2));
5682 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
5683 data_writes3, arraysize(data_writes3));
5684 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5685 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5686 session_deps_.socket_factory->AddSocketDataProvider(&data3);
5687
5688 TestCompletionCallback callback1;
5689
5690 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5691 EXPECT_EQ(ERR_IO_PENDING, rv);
5692
5693 rv = callback1.WaitForResult();
5694 EXPECT_EQ(OK, rv);
5695
5696 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
5697 TestCompletionCallback callback2;
5698 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
5699 EXPECT_EQ(ERR_IO_PENDING, rv);
5700 rv = callback2.WaitForResult();
5701 EXPECT_EQ(OK, rv);
5702 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5703
5704 const HttpResponseInfo* response = trans->GetResponseInfo();
5705 ASSERT_TRUE(response != NULL);
5706 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
5707
5708 TestCompletionCallback callback3;
5709
5710 rv = trans->RestartWithAuth(
5711 AuthCredentials(kFoo3, kBar3), callback3.callback());
5712 EXPECT_EQ(ERR_IO_PENDING, rv);
5713
5714 rv = callback3.WaitForResult();
5715 EXPECT_EQ(OK, rv);
5716
5717 response = trans->GetResponseInfo();
5718 ASSERT_TRUE(response != NULL);
5719 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5720 EXPECT_EQ(100, response->headers->GetContentLength());
5721 }
5722 }
5723
5724 // Tests that nonce count increments when multiple auth attempts
5725 // are started with the same nonce.
TEST_P(HttpNetworkTransactionTest,DigestPreAuthNonceCount)5726 TEST_P(HttpNetworkTransactionTest, DigestPreAuthNonceCount) {
5727 HttpAuthHandlerDigest::Factory* digest_factory =
5728 new HttpAuthHandlerDigest::Factory();
5729 HttpAuthHandlerDigest::FixedNonceGenerator* nonce_generator =
5730 new HttpAuthHandlerDigest::FixedNonceGenerator("0123456789abcdef");
5731 digest_factory->set_nonce_generator(nonce_generator);
5732 session_deps_.http_auth_handler_factory.reset(digest_factory);
5733 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5734
5735 // Transaction 1: authenticate (foo, bar) on MyRealm1
5736 {
5737 HttpRequestInfo request;
5738 request.method = "GET";
5739 request.url = GURL("http://www.google.com/x/y/z");
5740 request.load_flags = 0;
5741
5742 scoped_ptr<HttpTransaction> trans(
5743 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5744
5745 MockWrite data_writes1[] = {
5746 MockWrite("GET /x/y/z HTTP/1.1\r\n"
5747 "Host: www.google.com\r\n"
5748 "Connection: keep-alive\r\n\r\n"),
5749 };
5750
5751 MockRead data_reads1[] = {
5752 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5753 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
5754 "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
5755 MockRead(SYNCHRONOUS, OK),
5756 };
5757
5758 // Resend with authorization (username=foo, password=bar)
5759 MockWrite data_writes2[] = {
5760 MockWrite("GET /x/y/z HTTP/1.1\r\n"
5761 "Host: www.google.com\r\n"
5762 "Connection: keep-alive\r\n"
5763 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
5764 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
5765 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
5766 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
5767 };
5768
5769 // Sever accepts the authorization.
5770 MockRead data_reads2[] = {
5771 MockRead("HTTP/1.0 200 OK\r\n"),
5772 MockRead(SYNCHRONOUS, OK),
5773 };
5774
5775 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5776 data_writes1, arraysize(data_writes1));
5777 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5778 data_writes2, arraysize(data_writes2));
5779 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5780 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5781
5782 TestCompletionCallback callback1;
5783
5784 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5785 EXPECT_EQ(ERR_IO_PENDING, rv);
5786
5787 rv = callback1.WaitForResult();
5788 EXPECT_EQ(OK, rv);
5789
5790 const HttpResponseInfo* response = trans->GetResponseInfo();
5791 ASSERT_TRUE(response != NULL);
5792 EXPECT_TRUE(CheckDigestServerAuth(response->auth_challenge.get()));
5793
5794 TestCompletionCallback callback2;
5795
5796 rv = trans->RestartWithAuth(
5797 AuthCredentials(kFoo, kBar), callback2.callback());
5798 EXPECT_EQ(ERR_IO_PENDING, rv);
5799
5800 rv = callback2.WaitForResult();
5801 EXPECT_EQ(OK, rv);
5802
5803 response = trans->GetResponseInfo();
5804 ASSERT_TRUE(response != NULL);
5805 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5806 }
5807
5808 // ------------------------------------------------------------------------
5809
5810 // Transaction 2: Request another resource in digestive's protection space.
5811 // This will preemptively add an Authorization header which should have an
5812 // "nc" value of 2 (as compared to 1 in the first use.
5813 {
5814 HttpRequestInfo request;
5815 request.method = "GET";
5816 // Note that Transaction 1 was at /x/y/z, so this is in the same
5817 // protection space as digest.
5818 request.url = GURL("http://www.google.com/x/y/a/b");
5819 request.load_flags = 0;
5820
5821 scoped_ptr<HttpTransaction> trans(
5822 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5823
5824 MockWrite data_writes1[] = {
5825 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
5826 "Host: www.google.com\r\n"
5827 "Connection: keep-alive\r\n"
5828 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
5829 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
5830 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
5831 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
5832 };
5833
5834 // Sever accepts the authorization.
5835 MockRead data_reads1[] = {
5836 MockRead("HTTP/1.0 200 OK\r\n"),
5837 MockRead("Content-Length: 100\r\n\r\n"),
5838 MockRead(SYNCHRONOUS, OK),
5839 };
5840
5841 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5842 data_writes1, arraysize(data_writes1));
5843 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5844
5845 TestCompletionCallback callback1;
5846
5847 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5848 EXPECT_EQ(ERR_IO_PENDING, rv);
5849
5850 rv = callback1.WaitForResult();
5851 EXPECT_EQ(OK, rv);
5852
5853 const HttpResponseInfo* response = trans->GetResponseInfo();
5854 ASSERT_TRUE(response != NULL);
5855 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5856 }
5857 }
5858
5859 // Test the ResetStateForRestart() private method.
TEST_P(HttpNetworkTransactionTest,ResetStateForRestart)5860 TEST_P(HttpNetworkTransactionTest, ResetStateForRestart) {
5861 // Create a transaction (the dependencies aren't important).
5862 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5863 scoped_ptr<HttpNetworkTransaction> trans(
5864 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
5865
5866 // Setup some state (which we expect ResetStateForRestart() will clear).
5867 trans->read_buf_ = new IOBuffer(15);
5868 trans->read_buf_len_ = 15;
5869 trans->request_headers_.SetHeader("Authorization", "NTLM");
5870
5871 // Setup state in response_
5872 HttpResponseInfo* response = &trans->response_;
5873 response->auth_challenge = new AuthChallengeInfo();
5874 response->ssl_info.cert_status = static_cast<CertStatus>(-1); // Nonsensical.
5875 response->response_time = base::Time::Now();
5876 response->was_cached = true; // (Wouldn't ever actually be true...)
5877
5878 { // Setup state for response_.vary_data
5879 HttpRequestInfo request;
5880 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
5881 std::replace(temp.begin(), temp.end(), '\n', '\0');
5882 scoped_refptr<HttpResponseHeaders> headers(new HttpResponseHeaders(temp));
5883 request.extra_headers.SetHeader("Foo", "1");
5884 request.extra_headers.SetHeader("bar", "23");
5885 EXPECT_TRUE(response->vary_data.Init(request, *headers.get()));
5886 }
5887
5888 // Cause the above state to be reset.
5889 trans->ResetStateForRestart();
5890
5891 // Verify that the state that needed to be reset, has been reset.
5892 EXPECT_TRUE(trans->read_buf_.get() == NULL);
5893 EXPECT_EQ(0, trans->read_buf_len_);
5894 EXPECT_TRUE(trans->request_headers_.IsEmpty());
5895 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5896 EXPECT_TRUE(response->headers.get() == NULL);
5897 EXPECT_FALSE(response->was_cached);
5898 EXPECT_EQ(0U, response->ssl_info.cert_status);
5899 EXPECT_FALSE(response->vary_data.is_valid());
5900 }
5901
5902 // Test HTTPS connections to a site with a bad certificate
TEST_P(HttpNetworkTransactionTest,HTTPSBadCertificate)5903 TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificate) {
5904 HttpRequestInfo request;
5905 request.method = "GET";
5906 request.url = GURL("https://www.google.com/");
5907 request.load_flags = 0;
5908
5909 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5910 scoped_ptr<HttpTransaction> trans(
5911 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
5912
5913 MockWrite data_writes[] = {
5914 MockWrite("GET / HTTP/1.1\r\n"
5915 "Host: www.google.com\r\n"
5916 "Connection: keep-alive\r\n\r\n"),
5917 };
5918
5919 MockRead data_reads[] = {
5920 MockRead("HTTP/1.0 200 OK\r\n"),
5921 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5922 MockRead("Content-Length: 100\r\n\r\n"),
5923 MockRead(SYNCHRONOUS, OK),
5924 };
5925
5926 StaticSocketDataProvider ssl_bad_certificate;
5927 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5928 data_writes, arraysize(data_writes));
5929 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
5930 SSLSocketDataProvider ssl(ASYNC, OK);
5931
5932 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
5933 session_deps_.socket_factory->AddSocketDataProvider(&data);
5934 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
5935 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
5936
5937 TestCompletionCallback callback;
5938
5939 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5940 EXPECT_EQ(ERR_IO_PENDING, rv);
5941
5942 rv = callback.WaitForResult();
5943 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
5944
5945 rv = trans->RestartIgnoringLastError(callback.callback());
5946 EXPECT_EQ(ERR_IO_PENDING, rv);
5947
5948 rv = callback.WaitForResult();
5949 EXPECT_EQ(OK, rv);
5950
5951 const HttpResponseInfo* response = trans->GetResponseInfo();
5952
5953 ASSERT_TRUE(response != NULL);
5954 EXPECT_EQ(100, response->headers->GetContentLength());
5955 }
5956
5957 // Test HTTPS connections to a site with a bad certificate, going through a
5958 // proxy
TEST_P(HttpNetworkTransactionTest,HTTPSBadCertificateViaProxy)5959 TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
5960 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
5961
5962 HttpRequestInfo request;
5963 request.method = "GET";
5964 request.url = GURL("https://www.google.com/");
5965 request.load_flags = 0;
5966
5967 MockWrite proxy_writes[] = {
5968 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
5969 "Host: www.google.com\r\n"
5970 "Proxy-Connection: keep-alive\r\n\r\n"),
5971 };
5972
5973 MockRead proxy_reads[] = {
5974 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
5975 MockRead(SYNCHRONOUS, OK)
5976 };
5977
5978 MockWrite data_writes[] = {
5979 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
5980 "Host: www.google.com\r\n"
5981 "Proxy-Connection: keep-alive\r\n\r\n"),
5982 MockWrite("GET / HTTP/1.1\r\n"
5983 "Host: www.google.com\r\n"
5984 "Connection: keep-alive\r\n\r\n"),
5985 };
5986
5987 MockRead data_reads[] = {
5988 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
5989 MockRead("HTTP/1.0 200 OK\r\n"),
5990 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5991 MockRead("Content-Length: 100\r\n\r\n"),
5992 MockRead(SYNCHRONOUS, OK),
5993 };
5994
5995 StaticSocketDataProvider ssl_bad_certificate(
5996 proxy_reads, arraysize(proxy_reads),
5997 proxy_writes, arraysize(proxy_writes));
5998 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5999 data_writes, arraysize(data_writes));
6000 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
6001 SSLSocketDataProvider ssl(ASYNC, OK);
6002
6003 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
6004 session_deps_.socket_factory->AddSocketDataProvider(&data);
6005 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
6006 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6007
6008 TestCompletionCallback callback;
6009
6010 for (int i = 0; i < 2; i++) {
6011 session_deps_.socket_factory->ResetNextMockIndexes();
6012
6013 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6014 scoped_ptr<HttpTransaction> trans(
6015 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6016
6017 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6018 EXPECT_EQ(ERR_IO_PENDING, rv);
6019
6020 rv = callback.WaitForResult();
6021 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
6022
6023 rv = trans->RestartIgnoringLastError(callback.callback());
6024 EXPECT_EQ(ERR_IO_PENDING, rv);
6025
6026 rv = callback.WaitForResult();
6027 EXPECT_EQ(OK, rv);
6028
6029 const HttpResponseInfo* response = trans->GetResponseInfo();
6030
6031 ASSERT_TRUE(response != NULL);
6032 EXPECT_EQ(100, response->headers->GetContentLength());
6033 }
6034 }
6035
6036
6037 // Test HTTPS connections to a site, going through an HTTPS proxy
TEST_P(HttpNetworkTransactionTest,HTTPSViaHttpsProxy)6038 TEST_P(HttpNetworkTransactionTest, HTTPSViaHttpsProxy) {
6039 session_deps_.proxy_service.reset(
6040 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
6041 CapturingNetLog net_log;
6042 session_deps_.net_log = &net_log;
6043
6044 HttpRequestInfo request;
6045 request.method = "GET";
6046 request.url = GURL("https://www.google.com/");
6047 request.load_flags = 0;
6048
6049 MockWrite data_writes[] = {
6050 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6051 "Host: www.google.com\r\n"
6052 "Proxy-Connection: keep-alive\r\n\r\n"),
6053 MockWrite("GET / HTTP/1.1\r\n"
6054 "Host: www.google.com\r\n"
6055 "Connection: keep-alive\r\n\r\n"),
6056 };
6057
6058 MockRead data_reads[] = {
6059 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6060 MockRead("HTTP/1.1 200 OK\r\n"),
6061 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6062 MockRead("Content-Length: 100\r\n\r\n"),
6063 MockRead(SYNCHRONOUS, OK),
6064 };
6065
6066 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6067 data_writes, arraysize(data_writes));
6068 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
6069 SSLSocketDataProvider tunnel_ssl(ASYNC, OK); // SSL through the tunnel
6070
6071 session_deps_.socket_factory->AddSocketDataProvider(&data);
6072 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
6073 session_deps_.socket_factory->AddSSLSocketDataProvider(&tunnel_ssl);
6074
6075 TestCompletionCallback callback;
6076
6077 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6078 scoped_ptr<HttpTransaction> trans(
6079 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6080
6081 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6082 EXPECT_EQ(ERR_IO_PENDING, rv);
6083
6084 rv = callback.WaitForResult();
6085 EXPECT_EQ(OK, rv);
6086 const HttpResponseInfo* response = trans->GetResponseInfo();
6087
6088 ASSERT_TRUE(response != NULL);
6089
6090 EXPECT_TRUE(response->headers->IsKeepAlive());
6091 EXPECT_EQ(200, response->headers->response_code());
6092 EXPECT_EQ(100, response->headers->GetContentLength());
6093 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
6094
6095 LoadTimingInfo load_timing_info;
6096 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
6097 TestLoadTimingNotReusedWithPac(load_timing_info,
6098 CONNECT_TIMING_HAS_SSL_TIMES);
6099 }
6100
6101 // Test an HTTPS Proxy's ability to redirect a CONNECT request
TEST_P(HttpNetworkTransactionTest,RedirectOfHttpsConnectViaHttpsProxy)6102 TEST_P(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaHttpsProxy) {
6103 session_deps_.proxy_service.reset(
6104 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
6105 CapturingNetLog net_log;
6106 session_deps_.net_log = &net_log;
6107
6108 HttpRequestInfo request;
6109 request.method = "GET";
6110 request.url = GURL("https://www.google.com/");
6111 request.load_flags = 0;
6112
6113 MockWrite data_writes[] = {
6114 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6115 "Host: www.google.com\r\n"
6116 "Proxy-Connection: keep-alive\r\n\r\n"),
6117 };
6118
6119 MockRead data_reads[] = {
6120 MockRead("HTTP/1.1 302 Redirect\r\n"),
6121 MockRead("Location: http://login.example.com/\r\n"),
6122 MockRead("Content-Length: 0\r\n\r\n"),
6123 MockRead(SYNCHRONOUS, OK),
6124 };
6125
6126 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6127 data_writes, arraysize(data_writes));
6128 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
6129
6130 session_deps_.socket_factory->AddSocketDataProvider(&data);
6131 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
6132
6133 TestCompletionCallback callback;
6134
6135 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6136 scoped_ptr<HttpTransaction> trans(
6137 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6138
6139 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6140 EXPECT_EQ(ERR_IO_PENDING, rv);
6141
6142 rv = callback.WaitForResult();
6143 EXPECT_EQ(OK, rv);
6144 const HttpResponseInfo* response = trans->GetResponseInfo();
6145
6146 ASSERT_TRUE(response != NULL);
6147
6148 EXPECT_EQ(302, response->headers->response_code());
6149 std::string url;
6150 EXPECT_TRUE(response->headers->IsRedirect(&url));
6151 EXPECT_EQ("http://login.example.com/", url);
6152
6153 // In the case of redirects from proxies, HttpNetworkTransaction returns
6154 // timing for the proxy connection instead of the connection to the host,
6155 // and no send / receive times.
6156 // See HttpNetworkTransaction::OnHttpsProxyTunnelResponse.
6157 LoadTimingInfo load_timing_info;
6158 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
6159
6160 EXPECT_FALSE(load_timing_info.socket_reused);
6161 EXPECT_NE(net::NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
6162
6163 EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null());
6164 EXPECT_LE(load_timing_info.proxy_resolve_start,
6165 load_timing_info.proxy_resolve_end);
6166 EXPECT_LE(load_timing_info.proxy_resolve_end,
6167 load_timing_info.connect_timing.connect_start);
6168 ExpectConnectTimingHasTimes(
6169 load_timing_info.connect_timing,
6170 CONNECT_TIMING_HAS_DNS_TIMES | CONNECT_TIMING_HAS_SSL_TIMES);
6171
6172 EXPECT_TRUE(load_timing_info.send_start.is_null());
6173 EXPECT_TRUE(load_timing_info.send_end.is_null());
6174 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
6175 }
6176
6177 // Test an HTTPS (SPDY) Proxy's ability to redirect a CONNECT request
TEST_P(HttpNetworkTransactionTest,RedirectOfHttpsConnectViaSpdyProxy)6178 TEST_P(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaSpdyProxy) {
6179 session_deps_.proxy_service.reset(
6180 ProxyService::CreateFixed("https://proxy:70"));
6181
6182 HttpRequestInfo request;
6183 request.method = "GET";
6184 request.url = GURL("https://www.google.com/");
6185 request.load_flags = 0;
6186
6187 scoped_ptr<SpdyFrame> conn(spdy_util_.ConstructSpdyConnect(NULL, 0, 1,
6188 LOWEST));
6189 scoped_ptr<SpdyFrame> goaway(
6190 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
6191 MockWrite data_writes[] = {
6192 CreateMockWrite(*conn.get(), 0, SYNCHRONOUS),
6193 CreateMockWrite(*goaway.get(), 3, SYNCHRONOUS),
6194 };
6195
6196 static const char* const kExtraHeaders[] = {
6197 "location",
6198 "http://login.example.com/",
6199 };
6200 scoped_ptr<SpdyFrame> resp(
6201 spdy_util_.ConstructSpdySynReplyError("302 Redirect", kExtraHeaders,
6202 arraysize(kExtraHeaders)/2, 1));
6203 MockRead data_reads[] = {
6204 CreateMockRead(*resp.get(), 1, SYNCHRONOUS),
6205 MockRead(ASYNC, 0, 2), // EOF
6206 };
6207
6208 DelayedSocketData data(
6209 1, // wait for one write to finish before reading.
6210 data_reads, arraysize(data_reads),
6211 data_writes, arraysize(data_writes));
6212 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
6213 proxy_ssl.SetNextProto(GetParam());
6214
6215 session_deps_.socket_factory->AddSocketDataProvider(&data);
6216 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
6217
6218 TestCompletionCallback callback;
6219
6220 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6221 scoped_ptr<HttpTransaction> trans(
6222 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6223
6224 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6225 EXPECT_EQ(ERR_IO_PENDING, rv);
6226
6227 rv = callback.WaitForResult();
6228 EXPECT_EQ(OK, rv);
6229 const HttpResponseInfo* response = trans->GetResponseInfo();
6230
6231 ASSERT_TRUE(response != NULL);
6232
6233 EXPECT_EQ(302, response->headers->response_code());
6234 std::string url;
6235 EXPECT_TRUE(response->headers->IsRedirect(&url));
6236 EXPECT_EQ("http://login.example.com/", url);
6237 }
6238
6239 // Test that an HTTPS proxy's response to a CONNECT request is filtered.
TEST_P(HttpNetworkTransactionTest,ErrorResponseToHttpsConnectViaHttpsProxy)6240 TEST_P(HttpNetworkTransactionTest,
6241 ErrorResponseToHttpsConnectViaHttpsProxy) {
6242 session_deps_.proxy_service.reset(
6243 ProxyService::CreateFixed("https://proxy:70"));
6244
6245 HttpRequestInfo request;
6246 request.method = "GET";
6247 request.url = GURL("https://www.google.com/");
6248 request.load_flags = 0;
6249
6250 MockWrite data_writes[] = {
6251 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6252 "Host: www.google.com\r\n"
6253 "Proxy-Connection: keep-alive\r\n\r\n"),
6254 };
6255
6256 MockRead data_reads[] = {
6257 MockRead("HTTP/1.1 404 Not Found\r\n"),
6258 MockRead("Content-Length: 23\r\n\r\n"),
6259 MockRead("The host does not exist"),
6260 MockRead(SYNCHRONOUS, OK),
6261 };
6262
6263 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6264 data_writes, arraysize(data_writes));
6265 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
6266
6267 session_deps_.socket_factory->AddSocketDataProvider(&data);
6268 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
6269
6270 TestCompletionCallback callback;
6271
6272 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6273 scoped_ptr<HttpTransaction> trans(
6274 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6275
6276 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6277 EXPECT_EQ(ERR_IO_PENDING, rv);
6278
6279 rv = callback.WaitForResult();
6280 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
6281
6282 // TODO(ttuttle): Anything else to check here?
6283 }
6284
6285 // Test that a SPDY proxy's response to a CONNECT request is filtered.
TEST_P(HttpNetworkTransactionTest,ErrorResponseToHttpsConnectViaSpdyProxy)6286 TEST_P(HttpNetworkTransactionTest,
6287 ErrorResponseToHttpsConnectViaSpdyProxy) {
6288 session_deps_.proxy_service.reset(
6289 ProxyService::CreateFixed("https://proxy:70"));
6290
6291 HttpRequestInfo request;
6292 request.method = "GET";
6293 request.url = GURL("https://www.google.com/");
6294 request.load_flags = 0;
6295
6296 scoped_ptr<SpdyFrame> conn(spdy_util_.ConstructSpdyConnect(NULL, 0, 1,
6297 LOWEST));
6298 scoped_ptr<SpdyFrame> rst(
6299 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
6300 MockWrite data_writes[] = {
6301 CreateMockWrite(*conn.get(), 0, SYNCHRONOUS),
6302 CreateMockWrite(*rst.get(), 3, SYNCHRONOUS),
6303 };
6304
6305 static const char* const kExtraHeaders[] = {
6306 "location",
6307 "http://login.example.com/",
6308 };
6309 scoped_ptr<SpdyFrame> resp(
6310 spdy_util_.ConstructSpdySynReplyError("404 Not Found", kExtraHeaders,
6311 arraysize(kExtraHeaders)/2, 1));
6312 scoped_ptr<SpdyFrame> body(
6313 spdy_util_.ConstructSpdyBodyFrame(
6314 1, "The host does not exist", 23, true));
6315 MockRead data_reads[] = {
6316 CreateMockRead(*resp.get(), 1, SYNCHRONOUS),
6317 CreateMockRead(*body.get(), 2, SYNCHRONOUS),
6318 MockRead(ASYNC, 0, 4), // EOF
6319 };
6320
6321 DelayedSocketData data(
6322 1, // wait for one write to finish before reading.
6323 data_reads, arraysize(data_reads),
6324 data_writes, arraysize(data_writes));
6325 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
6326 proxy_ssl.SetNextProto(GetParam());
6327
6328 session_deps_.socket_factory->AddSocketDataProvider(&data);
6329 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
6330
6331 TestCompletionCallback callback;
6332
6333 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6334 scoped_ptr<HttpTransaction> trans(
6335 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6336
6337 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6338 EXPECT_EQ(ERR_IO_PENDING, rv);
6339
6340 rv = callback.WaitForResult();
6341 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
6342
6343 // TODO(ttuttle): Anything else to check here?
6344 }
6345
6346 // Test the request-challenge-retry sequence for basic auth, through
6347 // a SPDY proxy over a single SPDY session.
TEST_P(HttpNetworkTransactionTest,BasicAuthSpdyProxy)6348 TEST_P(HttpNetworkTransactionTest, BasicAuthSpdyProxy) {
6349 HttpRequestInfo request;
6350 request.method = "GET";
6351 request.url = GURL("https://www.google.com/");
6352 // when the no authentication data flag is set.
6353 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
6354
6355 // Configure against https proxy server "myproxy:70".
6356 session_deps_.proxy_service.reset(
6357 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70"));
6358 CapturingBoundNetLog log;
6359 session_deps_.net_log = log.bound().net_log();
6360 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6361
6362 // Since we have proxy, should try to establish tunnel.
6363 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyConnect(NULL, 0, 1,
6364 LOWEST));
6365 scoped_ptr<SpdyFrame> rst(
6366 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
6367
6368 // After calling trans->RestartWithAuth(), this is the request we should
6369 // be issuing -- the final header line contains the credentials.
6370 const char* const kAuthCredentials[] = {
6371 "proxy-authorization", "Basic Zm9vOmJhcg==",
6372 };
6373 scoped_ptr<SpdyFrame> connect2(spdy_util_.ConstructSpdyConnect(
6374 kAuthCredentials, arraysize(kAuthCredentials) / 2, 3, LOWEST));
6375 // fetch https://www.google.com/ via HTTP
6376 const char get[] = "GET / HTTP/1.1\r\n"
6377 "Host: www.google.com\r\n"
6378 "Connection: keep-alive\r\n\r\n";
6379 scoped_ptr<SpdyFrame> wrapped_get(
6380 spdy_util_.ConstructSpdyBodyFrame(3, get, strlen(get), false));
6381
6382 MockWrite spdy_writes[] = {
6383 CreateMockWrite(*req, 1, ASYNC),
6384 CreateMockWrite(*rst, 4, ASYNC),
6385 CreateMockWrite(*connect2, 5),
6386 CreateMockWrite(*wrapped_get, 8),
6387 };
6388
6389 // The proxy responds to the connect with a 407, using a persistent
6390 // connection.
6391 const char* const kAuthChallenge[] = {
6392 spdy_util_.GetStatusKey(), "407 Proxy Authentication Required",
6393 spdy_util_.GetVersionKey(), "HTTP/1.1",
6394 "proxy-authenticate", "Basic realm=\"MyRealm1\"",
6395 };
6396
6397 scoped_ptr<SpdyFrame> conn_auth_resp(
6398 spdy_util_.ConstructSpdyControlFrame(NULL,
6399 0,
6400 false,
6401 1,
6402 LOWEST,
6403 SYN_REPLY,
6404 CONTROL_FLAG_NONE,
6405 kAuthChallenge,
6406 arraysize(kAuthChallenge),
6407 0));
6408
6409 scoped_ptr<SpdyFrame> conn_resp(
6410 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
6411 const char resp[] = "HTTP/1.1 200 OK\r\n"
6412 "Content-Length: 5\r\n\r\n";
6413
6414 scoped_ptr<SpdyFrame> wrapped_get_resp(
6415 spdy_util_.ConstructSpdyBodyFrame(3, resp, strlen(resp), false));
6416 scoped_ptr<SpdyFrame> wrapped_body(
6417 spdy_util_.ConstructSpdyBodyFrame(3, "hello", 5, false));
6418 MockRead spdy_reads[] = {
6419 CreateMockRead(*conn_auth_resp, 2, ASYNC),
6420 CreateMockRead(*conn_resp, 6, ASYNC),
6421 CreateMockRead(*wrapped_get_resp, 9, ASYNC),
6422 CreateMockRead(*wrapped_body, 10, ASYNC),
6423 MockRead(ASYNC, OK, 11), // EOF. May or may not be read.
6424 };
6425
6426 OrderedSocketData spdy_data(
6427 spdy_reads, arraysize(spdy_reads),
6428 spdy_writes, arraysize(spdy_writes));
6429 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
6430 // Negotiate SPDY to the proxy
6431 SSLSocketDataProvider proxy(ASYNC, OK);
6432 proxy.SetNextProto(GetParam());
6433 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
6434 // Vanilla SSL to the server
6435 SSLSocketDataProvider server(ASYNC, OK);
6436 session_deps_.socket_factory->AddSSLSocketDataProvider(&server);
6437
6438 TestCompletionCallback callback1;
6439
6440 scoped_ptr<HttpTransaction> trans(
6441 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6442
6443 int rv = trans->Start(&request, callback1.callback(), log.bound());
6444 EXPECT_EQ(ERR_IO_PENDING, rv);
6445
6446 rv = callback1.WaitForResult();
6447 EXPECT_EQ(OK, rv);
6448 net::CapturingNetLog::CapturedEntryList entries;
6449 log.GetEntries(&entries);
6450 size_t pos = ExpectLogContainsSomewhere(
6451 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
6452 NetLog::PHASE_NONE);
6453 ExpectLogContainsSomewhere(
6454 entries, pos,
6455 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
6456 NetLog::PHASE_NONE);
6457
6458 const HttpResponseInfo* response = trans->GetResponseInfo();
6459 ASSERT_TRUE(response != NULL);
6460 ASSERT_FALSE(response->headers.get() == NULL);
6461 EXPECT_EQ(407, response->headers->response_code());
6462 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
6463 EXPECT_TRUE(response->auth_challenge.get() != NULL);
6464 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
6465
6466 TestCompletionCallback callback2;
6467
6468 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar),
6469 callback2.callback());
6470 EXPECT_EQ(ERR_IO_PENDING, rv);
6471
6472 rv = callback2.WaitForResult();
6473 EXPECT_EQ(OK, rv);
6474
6475 response = trans->GetResponseInfo();
6476 ASSERT_TRUE(response != NULL);
6477
6478 EXPECT_TRUE(response->headers->IsKeepAlive());
6479 EXPECT_EQ(200, response->headers->response_code());
6480 EXPECT_EQ(5, response->headers->GetContentLength());
6481 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
6482
6483 // The password prompt info should not be set.
6484 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6485
6486 LoadTimingInfo load_timing_info;
6487 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
6488 TestLoadTimingNotReusedWithPac(load_timing_info,
6489 CONNECT_TIMING_HAS_SSL_TIMES);
6490
6491 trans.reset();
6492 session->CloseAllConnections();
6493 }
6494
6495 // Test that an explicitly trusted SPDY proxy can push a resource from an
6496 // origin that is different from that of its associated resource.
TEST_P(HttpNetworkTransactionTest,CrossOriginProxyPush)6497 TEST_P(HttpNetworkTransactionTest, CrossOriginProxyPush) {
6498 HttpRequestInfo request;
6499 HttpRequestInfo push_request;
6500
6501 request.method = "GET";
6502 request.url = GURL("http://www.google.com/");
6503 push_request.method = "GET";
6504 push_request.url = GURL("http://www.another-origin.com/foo.dat");
6505
6506 // Configure against https proxy server "myproxy:70".
6507 session_deps_.proxy_service.reset(
6508 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70"));
6509 CapturingBoundNetLog log;
6510 session_deps_.net_log = log.bound().net_log();
6511
6512 // Enable cross-origin push.
6513 session_deps_.trusted_spdy_proxy = "myproxy:70";
6514
6515 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6516
6517 scoped_ptr<SpdyFrame> stream1_syn(
6518 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
6519
6520 MockWrite spdy_writes[] = {
6521 CreateMockWrite(*stream1_syn, 1, ASYNC),
6522 };
6523
6524 scoped_ptr<SpdyFrame>
6525 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
6526
6527 scoped_ptr<SpdyFrame>
6528 stream1_body(spdy_util_.ConstructSpdyBodyFrame(1, true));
6529
6530 scoped_ptr<SpdyFrame>
6531 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
6532 0,
6533 2,
6534 1,
6535 "http://www.another-origin.com/foo.dat"));
6536 const char kPushedData[] = "pushed";
6537 scoped_ptr<SpdyFrame> stream2_body(
6538 spdy_util_.ConstructSpdyBodyFrame(
6539 2, kPushedData, strlen(kPushedData), true));
6540
6541 MockRead spdy_reads[] = {
6542 CreateMockRead(*stream1_reply, 2, ASYNC),
6543 CreateMockRead(*stream2_syn, 3, ASYNC),
6544 CreateMockRead(*stream1_body, 4, ASYNC),
6545 CreateMockRead(*stream2_body, 5, ASYNC),
6546 MockRead(ASYNC, ERR_IO_PENDING, 6), // Force a pause
6547 };
6548
6549 OrderedSocketData spdy_data(
6550 spdy_reads, arraysize(spdy_reads),
6551 spdy_writes, arraysize(spdy_writes));
6552 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
6553 // Negotiate SPDY to the proxy
6554 SSLSocketDataProvider proxy(ASYNC, OK);
6555 proxy.SetNextProto(GetParam());
6556 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
6557
6558 scoped_ptr<HttpTransaction> trans(
6559 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6560 TestCompletionCallback callback;
6561 int rv = trans->Start(&request, callback.callback(), log.bound());
6562 EXPECT_EQ(ERR_IO_PENDING, rv);
6563
6564 rv = callback.WaitForResult();
6565 EXPECT_EQ(OK, rv);
6566 const HttpResponseInfo* response = trans->GetResponseInfo();
6567
6568 scoped_ptr<HttpTransaction> push_trans(
6569 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6570 rv = push_trans->Start(&push_request, callback.callback(), log.bound());
6571 EXPECT_EQ(ERR_IO_PENDING, rv);
6572
6573 rv = callback.WaitForResult();
6574 EXPECT_EQ(OK, rv);
6575 const HttpResponseInfo* push_response = push_trans->GetResponseInfo();
6576
6577 ASSERT_TRUE(response != NULL);
6578 EXPECT_TRUE(response->headers->IsKeepAlive());
6579
6580 EXPECT_EQ(200, response->headers->response_code());
6581 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
6582
6583 std::string response_data;
6584 rv = ReadTransaction(trans.get(), &response_data);
6585 EXPECT_EQ(OK, rv);
6586 EXPECT_EQ("hello!", response_data);
6587
6588 LoadTimingInfo load_timing_info;
6589 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
6590 TestLoadTimingNotReusedWithPac(load_timing_info,
6591 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
6592
6593 // Verify the pushed stream.
6594 EXPECT_TRUE(push_response->headers.get() != NULL);
6595 EXPECT_EQ(200, push_response->headers->response_code());
6596
6597 rv = ReadTransaction(push_trans.get(), &response_data);
6598 EXPECT_EQ(OK, rv);
6599 EXPECT_EQ("pushed", response_data);
6600
6601 LoadTimingInfo push_load_timing_info;
6602 EXPECT_TRUE(push_trans->GetLoadTimingInfo(&push_load_timing_info));
6603 TestLoadTimingReusedWithPac(push_load_timing_info);
6604 // The transactions should share a socket ID, despite being for different
6605 // origins.
6606 EXPECT_EQ(load_timing_info.socket_log_id,
6607 push_load_timing_info.socket_log_id);
6608
6609 trans.reset();
6610 push_trans.reset();
6611 session->CloseAllConnections();
6612 }
6613
6614 // Test that an explicitly trusted SPDY proxy cannot push HTTPS content.
TEST_P(HttpNetworkTransactionTest,CrossOriginProxyPushCorrectness)6615 TEST_P(HttpNetworkTransactionTest, CrossOriginProxyPushCorrectness) {
6616 HttpRequestInfo request;
6617
6618 request.method = "GET";
6619 request.url = GURL("http://www.google.com/");
6620
6621 // Configure against https proxy server "myproxy:70".
6622 session_deps_.proxy_service.reset(
6623 ProxyService::CreateFixed("https://myproxy:70"));
6624 CapturingBoundNetLog log;
6625 session_deps_.net_log = log.bound().net_log();
6626
6627 // Enable cross-origin push.
6628 session_deps_.trusted_spdy_proxy = "myproxy:70";
6629
6630 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6631
6632 scoped_ptr<SpdyFrame> stream1_syn(
6633 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
6634
6635 scoped_ptr<SpdyFrame> push_rst(
6636 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
6637
6638 MockWrite spdy_writes[] = {
6639 CreateMockWrite(*stream1_syn, 1, ASYNC),
6640 CreateMockWrite(*push_rst, 4),
6641 };
6642
6643 scoped_ptr<SpdyFrame>
6644 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
6645
6646 scoped_ptr<SpdyFrame>
6647 stream1_body(spdy_util_.ConstructSpdyBodyFrame(1, true));
6648
6649 scoped_ptr<SpdyFrame>
6650 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
6651 0,
6652 2,
6653 1,
6654 "https://www.another-origin.com/foo.dat"));
6655
6656 MockRead spdy_reads[] = {
6657 CreateMockRead(*stream1_reply, 2, ASYNC),
6658 CreateMockRead(*stream2_syn, 3, ASYNC),
6659 CreateMockRead(*stream1_body, 5, ASYNC),
6660 MockRead(ASYNC, ERR_IO_PENDING, 6), // Force a pause
6661 };
6662
6663 OrderedSocketData spdy_data(
6664 spdy_reads, arraysize(spdy_reads),
6665 spdy_writes, arraysize(spdy_writes));
6666 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
6667 // Negotiate SPDY to the proxy
6668 SSLSocketDataProvider proxy(ASYNC, OK);
6669 proxy.SetNextProto(GetParam());
6670 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
6671
6672 scoped_ptr<HttpTransaction> trans(
6673 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6674 TestCompletionCallback callback;
6675 int rv = trans->Start(&request, callback.callback(), log.bound());
6676 EXPECT_EQ(ERR_IO_PENDING, rv);
6677
6678 rv = callback.WaitForResult();
6679 EXPECT_EQ(OK, rv);
6680 const HttpResponseInfo* response = trans->GetResponseInfo();
6681
6682 ASSERT_TRUE(response != NULL);
6683 EXPECT_TRUE(response->headers->IsKeepAlive());
6684
6685 EXPECT_EQ(200, response->headers->response_code());
6686 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
6687
6688 std::string response_data;
6689 rv = ReadTransaction(trans.get(), &response_data);
6690 EXPECT_EQ(OK, rv);
6691 EXPECT_EQ("hello!", response_data);
6692
6693 trans.reset();
6694 session->CloseAllConnections();
6695 }
6696
6697 // Test HTTPS connections to a site with a bad certificate, going through an
6698 // HTTPS proxy
TEST_P(HttpNetworkTransactionTest,HTTPSBadCertificateViaHttpsProxy)6699 TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificateViaHttpsProxy) {
6700 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
6701 "https://proxy:70"));
6702
6703 HttpRequestInfo request;
6704 request.method = "GET";
6705 request.url = GURL("https://www.google.com/");
6706 request.load_flags = 0;
6707
6708 // Attempt to fetch the URL from a server with a bad cert
6709 MockWrite bad_cert_writes[] = {
6710 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6711 "Host: www.google.com\r\n"
6712 "Proxy-Connection: keep-alive\r\n\r\n"),
6713 };
6714
6715 MockRead bad_cert_reads[] = {
6716 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6717 MockRead(SYNCHRONOUS, OK)
6718 };
6719
6720 // Attempt to fetch the URL with a good cert
6721 MockWrite good_data_writes[] = {
6722 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6723 "Host: www.google.com\r\n"
6724 "Proxy-Connection: keep-alive\r\n\r\n"),
6725 MockWrite("GET / HTTP/1.1\r\n"
6726 "Host: www.google.com\r\n"
6727 "Connection: keep-alive\r\n\r\n"),
6728 };
6729
6730 MockRead good_cert_reads[] = {
6731 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6732 MockRead("HTTP/1.0 200 OK\r\n"),
6733 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6734 MockRead("Content-Length: 100\r\n\r\n"),
6735 MockRead(SYNCHRONOUS, OK),
6736 };
6737
6738 StaticSocketDataProvider ssl_bad_certificate(
6739 bad_cert_reads, arraysize(bad_cert_reads),
6740 bad_cert_writes, arraysize(bad_cert_writes));
6741 StaticSocketDataProvider data(good_cert_reads, arraysize(good_cert_reads),
6742 good_data_writes, arraysize(good_data_writes));
6743 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
6744 SSLSocketDataProvider ssl(ASYNC, OK);
6745
6746 // SSL to the proxy, then CONNECT request, then SSL with bad certificate
6747 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6748 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
6749 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
6750
6751 // SSL to the proxy, then CONNECT request, then valid SSL certificate
6752 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6753 session_deps_.socket_factory->AddSocketDataProvider(&data);
6754 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6755
6756 TestCompletionCallback callback;
6757
6758 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6759 scoped_ptr<HttpTransaction> trans(
6760 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6761
6762 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6763 EXPECT_EQ(ERR_IO_PENDING, rv);
6764
6765 rv = callback.WaitForResult();
6766 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
6767
6768 rv = trans->RestartIgnoringLastError(callback.callback());
6769 EXPECT_EQ(ERR_IO_PENDING, rv);
6770
6771 rv = callback.WaitForResult();
6772 EXPECT_EQ(OK, rv);
6773
6774 const HttpResponseInfo* response = trans->GetResponseInfo();
6775
6776 ASSERT_TRUE(response != NULL);
6777 EXPECT_EQ(100, response->headers->GetContentLength());
6778 }
6779
TEST_P(HttpNetworkTransactionTest,BuildRequest_UserAgent)6780 TEST_P(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
6781 HttpRequestInfo request;
6782 request.method = "GET";
6783 request.url = GURL("http://www.google.com/");
6784 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
6785 "Chromium Ultra Awesome X Edition");
6786
6787 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6788 scoped_ptr<HttpTransaction> trans(
6789 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6790
6791 MockWrite data_writes[] = {
6792 MockWrite("GET / HTTP/1.1\r\n"
6793 "Host: www.google.com\r\n"
6794 "Connection: keep-alive\r\n"
6795 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
6796 };
6797
6798 // Lastly, the server responds with the actual content.
6799 MockRead data_reads[] = {
6800 MockRead("HTTP/1.0 200 OK\r\n"),
6801 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6802 MockRead("Content-Length: 100\r\n\r\n"),
6803 MockRead(SYNCHRONOUS, OK),
6804 };
6805
6806 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6807 data_writes, arraysize(data_writes));
6808 session_deps_.socket_factory->AddSocketDataProvider(&data);
6809
6810 TestCompletionCallback callback;
6811
6812 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6813 EXPECT_EQ(ERR_IO_PENDING, rv);
6814
6815 rv = callback.WaitForResult();
6816 EXPECT_EQ(OK, rv);
6817 }
6818
TEST_P(HttpNetworkTransactionTest,BuildRequest_UserAgentOverTunnel)6819 TEST_P(HttpNetworkTransactionTest, BuildRequest_UserAgentOverTunnel) {
6820 HttpRequestInfo request;
6821 request.method = "GET";
6822 request.url = GURL("https://www.google.com/");
6823 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
6824 "Chromium Ultra Awesome X Edition");
6825
6826 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
6827 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6828 scoped_ptr<HttpTransaction> trans(
6829 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6830
6831 MockWrite data_writes[] = {
6832 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6833 "Host: www.google.com\r\n"
6834 "Proxy-Connection: keep-alive\r\n"
6835 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
6836 };
6837 MockRead data_reads[] = {
6838 // Return an error, so the transaction stops here (this test isn't
6839 // interested in the rest).
6840 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
6841 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6842 MockRead("Proxy-Connection: close\r\n\r\n"),
6843 };
6844
6845 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6846 data_writes, arraysize(data_writes));
6847 session_deps_.socket_factory->AddSocketDataProvider(&data);
6848
6849 TestCompletionCallback callback;
6850
6851 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6852 EXPECT_EQ(ERR_IO_PENDING, rv);
6853
6854 rv = callback.WaitForResult();
6855 EXPECT_EQ(OK, rv);
6856 }
6857
TEST_P(HttpNetworkTransactionTest,BuildRequest_Referer)6858 TEST_P(HttpNetworkTransactionTest, BuildRequest_Referer) {
6859 HttpRequestInfo request;
6860 request.method = "GET";
6861 request.url = GURL("http://www.google.com/");
6862 request.load_flags = 0;
6863 request.extra_headers.SetHeader(HttpRequestHeaders::kReferer,
6864 "http://the.previous.site.com/");
6865
6866 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6867 scoped_ptr<HttpTransaction> trans(
6868 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6869
6870 MockWrite data_writes[] = {
6871 MockWrite("GET / HTTP/1.1\r\n"
6872 "Host: www.google.com\r\n"
6873 "Connection: keep-alive\r\n"
6874 "Referer: http://the.previous.site.com/\r\n\r\n"),
6875 };
6876
6877 // Lastly, the server responds with the actual content.
6878 MockRead data_reads[] = {
6879 MockRead("HTTP/1.0 200 OK\r\n"),
6880 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6881 MockRead("Content-Length: 100\r\n\r\n"),
6882 MockRead(SYNCHRONOUS, OK),
6883 };
6884
6885 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6886 data_writes, arraysize(data_writes));
6887 session_deps_.socket_factory->AddSocketDataProvider(&data);
6888
6889 TestCompletionCallback callback;
6890
6891 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6892 EXPECT_EQ(ERR_IO_PENDING, rv);
6893
6894 rv = callback.WaitForResult();
6895 EXPECT_EQ(OK, rv);
6896 }
6897
TEST_P(HttpNetworkTransactionTest,BuildRequest_PostContentLengthZero)6898 TEST_P(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
6899 HttpRequestInfo request;
6900 request.method = "POST";
6901 request.url = GURL("http://www.google.com/");
6902
6903 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6904 scoped_ptr<HttpTransaction> trans(
6905 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6906
6907 MockWrite data_writes[] = {
6908 MockWrite("POST / HTTP/1.1\r\n"
6909 "Host: www.google.com\r\n"
6910 "Connection: keep-alive\r\n"
6911 "Content-Length: 0\r\n\r\n"),
6912 };
6913
6914 // Lastly, the server responds with the actual content.
6915 MockRead data_reads[] = {
6916 MockRead("HTTP/1.0 200 OK\r\n"),
6917 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6918 MockRead("Content-Length: 100\r\n\r\n"),
6919 MockRead(SYNCHRONOUS, OK),
6920 };
6921
6922 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6923 data_writes, arraysize(data_writes));
6924 session_deps_.socket_factory->AddSocketDataProvider(&data);
6925
6926 TestCompletionCallback callback;
6927
6928 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6929 EXPECT_EQ(ERR_IO_PENDING, rv);
6930
6931 rv = callback.WaitForResult();
6932 EXPECT_EQ(OK, rv);
6933 }
6934
TEST_P(HttpNetworkTransactionTest,BuildRequest_PutContentLengthZero)6935 TEST_P(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
6936 HttpRequestInfo request;
6937 request.method = "PUT";
6938 request.url = GURL("http://www.google.com/");
6939
6940 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6941 scoped_ptr<HttpTransaction> trans(
6942 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6943
6944 MockWrite data_writes[] = {
6945 MockWrite("PUT / HTTP/1.1\r\n"
6946 "Host: www.google.com\r\n"
6947 "Connection: keep-alive\r\n"
6948 "Content-Length: 0\r\n\r\n"),
6949 };
6950
6951 // Lastly, the server responds with the actual content.
6952 MockRead data_reads[] = {
6953 MockRead("HTTP/1.0 200 OK\r\n"),
6954 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6955 MockRead("Content-Length: 100\r\n\r\n"),
6956 MockRead(SYNCHRONOUS, OK),
6957 };
6958
6959 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6960 data_writes, arraysize(data_writes));
6961 session_deps_.socket_factory->AddSocketDataProvider(&data);
6962
6963 TestCompletionCallback callback;
6964
6965 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6966 EXPECT_EQ(ERR_IO_PENDING, rv);
6967
6968 rv = callback.WaitForResult();
6969 EXPECT_EQ(OK, rv);
6970 }
6971
TEST_P(HttpNetworkTransactionTest,BuildRequest_HeadContentLengthZero)6972 TEST_P(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
6973 HttpRequestInfo request;
6974 request.method = "HEAD";
6975 request.url = GURL("http://www.google.com/");
6976
6977 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6978 scoped_ptr<HttpTransaction> trans(
6979 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6980
6981 MockWrite data_writes[] = {
6982 MockWrite("HEAD / HTTP/1.1\r\n"
6983 "Host: www.google.com\r\n"
6984 "Connection: keep-alive\r\n"
6985 "Content-Length: 0\r\n\r\n"),
6986 };
6987
6988 // Lastly, the server responds with the actual content.
6989 MockRead data_reads[] = {
6990 MockRead("HTTP/1.0 200 OK\r\n"),
6991 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6992 MockRead("Content-Length: 100\r\n\r\n"),
6993 MockRead(SYNCHRONOUS, OK),
6994 };
6995
6996 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6997 data_writes, arraysize(data_writes));
6998 session_deps_.socket_factory->AddSocketDataProvider(&data);
6999
7000 TestCompletionCallback callback;
7001
7002 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7003 EXPECT_EQ(ERR_IO_PENDING, rv);
7004
7005 rv = callback.WaitForResult();
7006 EXPECT_EQ(OK, rv);
7007 }
7008
TEST_P(HttpNetworkTransactionTest,BuildRequest_CacheControlNoCache)7009 TEST_P(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
7010 HttpRequestInfo request;
7011 request.method = "GET";
7012 request.url = GURL("http://www.google.com/");
7013 request.load_flags = LOAD_BYPASS_CACHE;
7014
7015 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7016 scoped_ptr<HttpTransaction> trans(
7017 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
7018
7019 MockWrite data_writes[] = {
7020 MockWrite("GET / HTTP/1.1\r\n"
7021 "Host: www.google.com\r\n"
7022 "Connection: keep-alive\r\n"
7023 "Pragma: no-cache\r\n"
7024 "Cache-Control: no-cache\r\n\r\n"),
7025 };
7026
7027 // Lastly, the server responds with the actual content.
7028 MockRead data_reads[] = {
7029 MockRead("HTTP/1.0 200 OK\r\n"),
7030 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7031 MockRead("Content-Length: 100\r\n\r\n"),
7032 MockRead(SYNCHRONOUS, OK),
7033 };
7034
7035 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7036 data_writes, arraysize(data_writes));
7037 session_deps_.socket_factory->AddSocketDataProvider(&data);
7038
7039 TestCompletionCallback callback;
7040
7041 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7042 EXPECT_EQ(ERR_IO_PENDING, rv);
7043
7044 rv = callback.WaitForResult();
7045 EXPECT_EQ(OK, rv);
7046 }
7047
TEST_P(HttpNetworkTransactionTest,BuildRequest_CacheControlValidateCache)7048 TEST_P(HttpNetworkTransactionTest,
7049 BuildRequest_CacheControlValidateCache) {
7050 HttpRequestInfo request;
7051 request.method = "GET";
7052 request.url = GURL("http://www.google.com/");
7053 request.load_flags = LOAD_VALIDATE_CACHE;
7054
7055 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7056 scoped_ptr<HttpTransaction> trans(
7057 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
7058
7059 MockWrite data_writes[] = {
7060 MockWrite("GET / HTTP/1.1\r\n"
7061 "Host: www.google.com\r\n"
7062 "Connection: keep-alive\r\n"
7063 "Cache-Control: max-age=0\r\n\r\n"),
7064 };
7065
7066 // Lastly, the server responds with the actual content.
7067 MockRead data_reads[] = {
7068 MockRead("HTTP/1.0 200 OK\r\n"),
7069 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7070 MockRead("Content-Length: 100\r\n\r\n"),
7071 MockRead(SYNCHRONOUS, OK),
7072 };
7073
7074 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7075 data_writes, arraysize(data_writes));
7076 session_deps_.socket_factory->AddSocketDataProvider(&data);
7077
7078 TestCompletionCallback callback;
7079
7080 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7081 EXPECT_EQ(ERR_IO_PENDING, rv);
7082
7083 rv = callback.WaitForResult();
7084 EXPECT_EQ(OK, rv);
7085 }
7086
TEST_P(HttpNetworkTransactionTest,BuildRequest_ExtraHeaders)7087 TEST_P(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
7088 HttpRequestInfo request;
7089 request.method = "GET";
7090 request.url = GURL("http://www.google.com/");
7091 request.extra_headers.SetHeader("FooHeader", "Bar");
7092
7093 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7094 scoped_ptr<HttpTransaction> trans(
7095 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
7096
7097 MockWrite data_writes[] = {
7098 MockWrite("GET / HTTP/1.1\r\n"
7099 "Host: www.google.com\r\n"
7100 "Connection: keep-alive\r\n"
7101 "FooHeader: Bar\r\n\r\n"),
7102 };
7103
7104 // Lastly, the server responds with the actual content.
7105 MockRead data_reads[] = {
7106 MockRead("HTTP/1.0 200 OK\r\n"),
7107 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7108 MockRead("Content-Length: 100\r\n\r\n"),
7109 MockRead(SYNCHRONOUS, OK),
7110 };
7111
7112 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7113 data_writes, arraysize(data_writes));
7114 session_deps_.socket_factory->AddSocketDataProvider(&data);
7115
7116 TestCompletionCallback callback;
7117
7118 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7119 EXPECT_EQ(ERR_IO_PENDING, rv);
7120
7121 rv = callback.WaitForResult();
7122 EXPECT_EQ(OK, rv);
7123 }
7124
TEST_P(HttpNetworkTransactionTest,BuildRequest_ExtraHeadersStripped)7125 TEST_P(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) {
7126 HttpRequestInfo request;
7127 request.method = "GET";
7128 request.url = GURL("http://www.google.com/");
7129 request.extra_headers.SetHeader("referer", "www.foo.com");
7130 request.extra_headers.SetHeader("hEllo", "Kitty");
7131 request.extra_headers.SetHeader("FoO", "bar");
7132
7133 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7134 scoped_ptr<HttpTransaction> trans(
7135 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
7136
7137 MockWrite data_writes[] = {
7138 MockWrite("GET / HTTP/1.1\r\n"
7139 "Host: www.google.com\r\n"
7140 "Connection: keep-alive\r\n"
7141 "referer: www.foo.com\r\n"
7142 "hEllo: Kitty\r\n"
7143 "FoO: bar\r\n\r\n"),
7144 };
7145
7146 // Lastly, the server responds with the actual content.
7147 MockRead data_reads[] = {
7148 MockRead("HTTP/1.0 200 OK\r\n"),
7149 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7150 MockRead("Content-Length: 100\r\n\r\n"),
7151 MockRead(SYNCHRONOUS, OK),
7152 };
7153
7154 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7155 data_writes, arraysize(data_writes));
7156 session_deps_.socket_factory->AddSocketDataProvider(&data);
7157
7158 TestCompletionCallback callback;
7159
7160 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7161 EXPECT_EQ(ERR_IO_PENDING, rv);
7162
7163 rv = callback.WaitForResult();
7164 EXPECT_EQ(OK, rv);
7165 }
7166
TEST_P(HttpNetworkTransactionTest,SOCKS4_HTTP_GET)7167 TEST_P(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
7168 HttpRequestInfo request;
7169 request.method = "GET";
7170 request.url = GURL("http://www.google.com/");
7171 request.load_flags = 0;
7172
7173 session_deps_.proxy_service.reset(
7174 ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080"));
7175 CapturingNetLog net_log;
7176 session_deps_.net_log = &net_log;
7177
7178 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7179 scoped_ptr<HttpTransaction> trans(
7180 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
7181
7182 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
7183 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7184
7185 MockWrite data_writes[] = {
7186 MockWrite(ASYNC, write_buffer, arraysize(write_buffer)),
7187 MockWrite("GET / HTTP/1.1\r\n"
7188 "Host: www.google.com\r\n"
7189 "Connection: keep-alive\r\n\r\n")
7190 };
7191
7192 MockRead data_reads[] = {
7193 MockRead(ASYNC, read_buffer, arraysize(read_buffer)),
7194 MockRead("HTTP/1.0 200 OK\r\n"),
7195 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7196 MockRead("Payload"),
7197 MockRead(SYNCHRONOUS, OK)
7198 };
7199
7200 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7201 data_writes, arraysize(data_writes));
7202 session_deps_.socket_factory->AddSocketDataProvider(&data);
7203
7204 TestCompletionCallback callback;
7205
7206 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7207 EXPECT_EQ(ERR_IO_PENDING, rv);
7208
7209 rv = callback.WaitForResult();
7210 EXPECT_EQ(OK, rv);
7211
7212 const HttpResponseInfo* response = trans->GetResponseInfo();
7213 ASSERT_TRUE(response != NULL);
7214
7215 LoadTimingInfo load_timing_info;
7216 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7217 TestLoadTimingNotReusedWithPac(load_timing_info,
7218 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
7219
7220 std::string response_text;
7221 rv = ReadTransaction(trans.get(), &response_text);
7222 EXPECT_EQ(OK, rv);
7223 EXPECT_EQ("Payload", response_text);
7224 }
7225
TEST_P(HttpNetworkTransactionTest,SOCKS4_SSL_GET)7226 TEST_P(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
7227 HttpRequestInfo request;
7228 request.method = "GET";
7229 request.url = GURL("https://www.google.com/");
7230 request.load_flags = 0;
7231
7232 session_deps_.proxy_service.reset(
7233 ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080"));
7234 CapturingNetLog net_log;
7235 session_deps_.net_log = &net_log;
7236
7237 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7238 scoped_ptr<HttpTransaction> trans(
7239 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
7240
7241 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
7242 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7243
7244 MockWrite data_writes[] = {
7245 MockWrite(ASYNC, reinterpret_cast<char*>(write_buffer),
7246 arraysize(write_buffer)),
7247 MockWrite("GET / HTTP/1.1\r\n"
7248 "Host: www.google.com\r\n"
7249 "Connection: keep-alive\r\n\r\n")
7250 };
7251
7252 MockRead data_reads[] = {
7253 MockRead(ASYNC, reinterpret_cast<char*>(read_buffer),
7254 arraysize(read_buffer)),
7255 MockRead("HTTP/1.0 200 OK\r\n"),
7256 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7257 MockRead("Payload"),
7258 MockRead(SYNCHRONOUS, OK)
7259 };
7260
7261 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7262 data_writes, arraysize(data_writes));
7263 session_deps_.socket_factory->AddSocketDataProvider(&data);
7264
7265 SSLSocketDataProvider ssl(ASYNC, OK);
7266 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7267
7268 TestCompletionCallback callback;
7269
7270 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7271 EXPECT_EQ(ERR_IO_PENDING, rv);
7272
7273 rv = callback.WaitForResult();
7274 EXPECT_EQ(OK, rv);
7275
7276 LoadTimingInfo load_timing_info;
7277 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7278 TestLoadTimingNotReusedWithPac(load_timing_info,
7279 CONNECT_TIMING_HAS_SSL_TIMES);
7280
7281 const HttpResponseInfo* response = trans->GetResponseInfo();
7282 ASSERT_TRUE(response != NULL);
7283
7284 std::string response_text;
7285 rv = ReadTransaction(trans.get(), &response_text);
7286 EXPECT_EQ(OK, rv);
7287 EXPECT_EQ("Payload", response_text);
7288 }
7289
TEST_P(HttpNetworkTransactionTest,SOCKS4_HTTP_GET_no_PAC)7290 TEST_P(HttpNetworkTransactionTest, SOCKS4_HTTP_GET_no_PAC) {
7291 HttpRequestInfo request;
7292 request.method = "GET";
7293 request.url = GURL("http://www.google.com/");
7294 request.load_flags = 0;
7295
7296 session_deps_.proxy_service.reset(
7297 ProxyService::CreateFixed("socks4://myproxy:1080"));
7298 CapturingNetLog net_log;
7299 session_deps_.net_log = &net_log;
7300
7301 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7302 scoped_ptr<HttpTransaction> trans(
7303 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
7304
7305 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
7306 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7307
7308 MockWrite data_writes[] = {
7309 MockWrite(ASYNC, write_buffer, arraysize(write_buffer)),
7310 MockWrite("GET / HTTP/1.1\r\n"
7311 "Host: www.google.com\r\n"
7312 "Connection: keep-alive\r\n\r\n")
7313 };
7314
7315 MockRead data_reads[] = {
7316 MockRead(ASYNC, read_buffer, arraysize(read_buffer)),
7317 MockRead("HTTP/1.0 200 OK\r\n"),
7318 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7319 MockRead("Payload"),
7320 MockRead(SYNCHRONOUS, OK)
7321 };
7322
7323 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7324 data_writes, arraysize(data_writes));
7325 session_deps_.socket_factory->AddSocketDataProvider(&data);
7326
7327 TestCompletionCallback callback;
7328
7329 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7330 EXPECT_EQ(ERR_IO_PENDING, rv);
7331
7332 rv = callback.WaitForResult();
7333 EXPECT_EQ(OK, rv);
7334
7335 const HttpResponseInfo* response = trans->GetResponseInfo();
7336 ASSERT_TRUE(response != NULL);
7337
7338 LoadTimingInfo load_timing_info;
7339 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7340 TestLoadTimingNotReused(load_timing_info,
7341 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
7342
7343 std::string response_text;
7344 rv = ReadTransaction(trans.get(), &response_text);
7345 EXPECT_EQ(OK, rv);
7346 EXPECT_EQ("Payload", response_text);
7347 }
7348
TEST_P(HttpNetworkTransactionTest,SOCKS5_HTTP_GET)7349 TEST_P(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
7350 HttpRequestInfo request;
7351 request.method = "GET";
7352 request.url = GURL("http://www.google.com/");
7353 request.load_flags = 0;
7354
7355 session_deps_.proxy_service.reset(
7356 ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080"));
7357 CapturingNetLog net_log;
7358 session_deps_.net_log = &net_log;
7359
7360 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7361 scoped_ptr<HttpTransaction> trans(
7362 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
7363
7364 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
7365 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
7366 const char kSOCKS5OkRequest[] = {
7367 0x05, // Version
7368 0x01, // Command (CONNECT)
7369 0x00, // Reserved.
7370 0x03, // Address type (DOMAINNAME).
7371 0x0E, // Length of domain (14)
7372 // Domain string:
7373 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
7374 0x00, 0x50, // 16-bit port (80)
7375 };
7376 const char kSOCKS5OkResponse[] =
7377 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
7378
7379 MockWrite data_writes[] = {
7380 MockWrite(ASYNC, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
7381 MockWrite(ASYNC, kSOCKS5OkRequest, arraysize(kSOCKS5OkRequest)),
7382 MockWrite("GET / HTTP/1.1\r\n"
7383 "Host: www.google.com\r\n"
7384 "Connection: keep-alive\r\n\r\n")
7385 };
7386
7387 MockRead data_reads[] = {
7388 MockRead(ASYNC, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
7389 MockRead(ASYNC, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
7390 MockRead("HTTP/1.0 200 OK\r\n"),
7391 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7392 MockRead("Payload"),
7393 MockRead(SYNCHRONOUS, OK)
7394 };
7395
7396 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7397 data_writes, arraysize(data_writes));
7398 session_deps_.socket_factory->AddSocketDataProvider(&data);
7399
7400 TestCompletionCallback callback;
7401
7402 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7403 EXPECT_EQ(ERR_IO_PENDING, rv);
7404
7405 rv = callback.WaitForResult();
7406 EXPECT_EQ(OK, rv);
7407
7408 const HttpResponseInfo* response = trans->GetResponseInfo();
7409 ASSERT_TRUE(response != NULL);
7410
7411 LoadTimingInfo load_timing_info;
7412 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7413 TestLoadTimingNotReusedWithPac(load_timing_info,
7414 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
7415
7416 std::string response_text;
7417 rv = ReadTransaction(trans.get(), &response_text);
7418 EXPECT_EQ(OK, rv);
7419 EXPECT_EQ("Payload", response_text);
7420 }
7421
TEST_P(HttpNetworkTransactionTest,SOCKS5_SSL_GET)7422 TEST_P(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
7423 HttpRequestInfo request;
7424 request.method = "GET";
7425 request.url = GURL("https://www.google.com/");
7426 request.load_flags = 0;
7427
7428 session_deps_.proxy_service.reset(
7429 ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080"));
7430 CapturingNetLog net_log;
7431 session_deps_.net_log = &net_log;
7432
7433 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7434 scoped_ptr<HttpTransaction> trans(
7435 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
7436
7437 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
7438 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
7439 const unsigned char kSOCKS5OkRequest[] = {
7440 0x05, // Version
7441 0x01, // Command (CONNECT)
7442 0x00, // Reserved.
7443 0x03, // Address type (DOMAINNAME).
7444 0x0E, // Length of domain (14)
7445 // Domain string:
7446 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
7447 0x01, 0xBB, // 16-bit port (443)
7448 };
7449
7450 const char kSOCKS5OkResponse[] =
7451 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
7452
7453 MockWrite data_writes[] = {
7454 MockWrite(ASYNC, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
7455 MockWrite(ASYNC, reinterpret_cast<const char*>(kSOCKS5OkRequest),
7456 arraysize(kSOCKS5OkRequest)),
7457 MockWrite("GET / HTTP/1.1\r\n"
7458 "Host: www.google.com\r\n"
7459 "Connection: keep-alive\r\n\r\n")
7460 };
7461
7462 MockRead data_reads[] = {
7463 MockRead(ASYNC, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
7464 MockRead(ASYNC, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
7465 MockRead("HTTP/1.0 200 OK\r\n"),
7466 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7467 MockRead("Payload"),
7468 MockRead(SYNCHRONOUS, OK)
7469 };
7470
7471 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7472 data_writes, arraysize(data_writes));
7473 session_deps_.socket_factory->AddSocketDataProvider(&data);
7474
7475 SSLSocketDataProvider ssl(ASYNC, OK);
7476 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7477
7478 TestCompletionCallback callback;
7479
7480 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7481 EXPECT_EQ(ERR_IO_PENDING, rv);
7482
7483 rv = callback.WaitForResult();
7484 EXPECT_EQ(OK, rv);
7485
7486 const HttpResponseInfo* response = trans->GetResponseInfo();
7487 ASSERT_TRUE(response != NULL);
7488
7489 LoadTimingInfo load_timing_info;
7490 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7491 TestLoadTimingNotReusedWithPac(load_timing_info,
7492 CONNECT_TIMING_HAS_SSL_TIMES);
7493
7494 std::string response_text;
7495 rv = ReadTransaction(trans.get(), &response_text);
7496 EXPECT_EQ(OK, rv);
7497 EXPECT_EQ("Payload", response_text);
7498 }
7499
7500 namespace {
7501
7502 // Tests that for connection endpoints the group names are correctly set.
7503
7504 struct GroupNameTest {
7505 std::string proxy_server;
7506 std::string url;
7507 std::string expected_group_name;
7508 bool ssl;
7509 };
7510
SetupSessionForGroupNameTests(NextProto next_proto,SpdySessionDependencies * session_deps_)7511 scoped_refptr<HttpNetworkSession> SetupSessionForGroupNameTests(
7512 NextProto next_proto,
7513 SpdySessionDependencies* session_deps_) {
7514 scoped_refptr<HttpNetworkSession> session(CreateSession(session_deps_));
7515
7516 base::WeakPtr<HttpServerProperties> http_server_properties =
7517 session->http_server_properties();
7518 http_server_properties->SetAlternateProtocol(
7519 HostPortPair("host.with.alternate", 80), 443,
7520 AlternateProtocolFromNextProto(next_proto));
7521
7522 return session;
7523 }
7524
GroupNameTransactionHelper(const std::string & url,const scoped_refptr<HttpNetworkSession> & session)7525 int GroupNameTransactionHelper(
7526 const std::string& url,
7527 const scoped_refptr<HttpNetworkSession>& session) {
7528 HttpRequestInfo request;
7529 request.method = "GET";
7530 request.url = GURL(url);
7531 request.load_flags = 0;
7532
7533 scoped_ptr<HttpTransaction> trans(
7534 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7535
7536 TestCompletionCallback callback;
7537
7538 // We do not complete this request, the dtor will clean the transaction up.
7539 return trans->Start(&request, callback.callback(), BoundNetLog());
7540 }
7541
7542 } // namespace
7543
TEST_P(HttpNetworkTransactionTest,GroupNameForDirectConnections)7544 TEST_P(HttpNetworkTransactionTest, GroupNameForDirectConnections) {
7545 const GroupNameTest tests[] = {
7546 {
7547 "", // unused
7548 "http://www.google.com/direct",
7549 "www.google.com:80",
7550 false,
7551 },
7552 {
7553 "", // unused
7554 "http://[2001:1418:13:1::25]/direct",
7555 "[2001:1418:13:1::25]:80",
7556 false,
7557 },
7558
7559 // SSL Tests
7560 {
7561 "", // unused
7562 "https://www.google.com/direct_ssl",
7563 "ssl/www.google.com:443",
7564 true,
7565 },
7566 {
7567 "", // unused
7568 "https://[2001:1418:13:1::25]/direct",
7569 "ssl/[2001:1418:13:1::25]:443",
7570 true,
7571 },
7572 {
7573 "", // unused
7574 "http://host.with.alternate/direct",
7575 "ssl/host.with.alternate:443",
7576 true,
7577 },
7578 };
7579
7580 session_deps_.use_alternate_protocols = true;
7581
7582 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
7583 session_deps_.proxy_service.reset(
7584 ProxyService::CreateFixed(tests[i].proxy_server));
7585 scoped_refptr<HttpNetworkSession> session(
7586 SetupSessionForGroupNameTests(GetParam(), &session_deps_));
7587
7588 HttpNetworkSessionPeer peer(session);
7589 CaptureGroupNameTransportSocketPool* transport_conn_pool =
7590 new CaptureGroupNameTransportSocketPool(NULL, NULL);
7591 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
7592 new CaptureGroupNameSSLSocketPool(NULL, NULL);
7593 scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
7594 new MockClientSocketPoolManager);
7595 mock_pool_manager->SetTransportSocketPool(transport_conn_pool);
7596 mock_pool_manager->SetSSLSocketPool(ssl_conn_pool);
7597 peer.SetClientSocketPoolManager(
7598 mock_pool_manager.PassAs<ClientSocketPoolManager>());
7599
7600 EXPECT_EQ(ERR_IO_PENDING,
7601 GroupNameTransactionHelper(tests[i].url, session));
7602 if (tests[i].ssl)
7603 EXPECT_EQ(tests[i].expected_group_name,
7604 ssl_conn_pool->last_group_name_received());
7605 else
7606 EXPECT_EQ(tests[i].expected_group_name,
7607 transport_conn_pool->last_group_name_received());
7608 }
7609
7610 }
7611
TEST_P(HttpNetworkTransactionTest,GroupNameForHTTPProxyConnections)7612 TEST_P(HttpNetworkTransactionTest, GroupNameForHTTPProxyConnections) {
7613 const GroupNameTest tests[] = {
7614 {
7615 "http_proxy",
7616 "http://www.google.com/http_proxy_normal",
7617 "www.google.com:80",
7618 false,
7619 },
7620
7621 // SSL Tests
7622 {
7623 "http_proxy",
7624 "https://www.google.com/http_connect_ssl",
7625 "ssl/www.google.com:443",
7626 true,
7627 },
7628
7629 {
7630 "http_proxy",
7631 "http://host.with.alternate/direct",
7632 "ssl/host.with.alternate:443",
7633 true,
7634 },
7635
7636 {
7637 "http_proxy",
7638 "ftp://ftp.google.com/http_proxy_normal",
7639 "ftp/ftp.google.com:21",
7640 false,
7641 },
7642 };
7643
7644 session_deps_.use_alternate_protocols = true;
7645
7646 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
7647 session_deps_.proxy_service.reset(
7648 ProxyService::CreateFixed(tests[i].proxy_server));
7649 scoped_refptr<HttpNetworkSession> session(
7650 SetupSessionForGroupNameTests(GetParam(), &session_deps_));
7651
7652 HttpNetworkSessionPeer peer(session);
7653
7654 HostPortPair proxy_host("http_proxy", 80);
7655 CaptureGroupNameHttpProxySocketPool* http_proxy_pool =
7656 new CaptureGroupNameHttpProxySocketPool(NULL, NULL);
7657 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
7658 new CaptureGroupNameSSLSocketPool(NULL, NULL);
7659
7660 scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
7661 new MockClientSocketPoolManager);
7662 mock_pool_manager->SetSocketPoolForHTTPProxy(proxy_host, http_proxy_pool);
7663 mock_pool_manager->SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
7664 peer.SetClientSocketPoolManager(
7665 mock_pool_manager.PassAs<ClientSocketPoolManager>());
7666
7667 EXPECT_EQ(ERR_IO_PENDING,
7668 GroupNameTransactionHelper(tests[i].url, session));
7669 if (tests[i].ssl)
7670 EXPECT_EQ(tests[i].expected_group_name,
7671 ssl_conn_pool->last_group_name_received());
7672 else
7673 EXPECT_EQ(tests[i].expected_group_name,
7674 http_proxy_pool->last_group_name_received());
7675 }
7676 }
7677
TEST_P(HttpNetworkTransactionTest,GroupNameForSOCKSConnections)7678 TEST_P(HttpNetworkTransactionTest, GroupNameForSOCKSConnections) {
7679 const GroupNameTest tests[] = {
7680 {
7681 "socks4://socks_proxy:1080",
7682 "http://www.google.com/socks4_direct",
7683 "socks4/www.google.com:80",
7684 false,
7685 },
7686 {
7687 "socks5://socks_proxy:1080",
7688 "http://www.google.com/socks5_direct",
7689 "socks5/www.google.com:80",
7690 false,
7691 },
7692
7693 // SSL Tests
7694 {
7695 "socks4://socks_proxy:1080",
7696 "https://www.google.com/socks4_ssl",
7697 "socks4/ssl/www.google.com:443",
7698 true,
7699 },
7700 {
7701 "socks5://socks_proxy:1080",
7702 "https://www.google.com/socks5_ssl",
7703 "socks5/ssl/www.google.com:443",
7704 true,
7705 },
7706
7707 {
7708 "socks4://socks_proxy:1080",
7709 "http://host.with.alternate/direct",
7710 "socks4/ssl/host.with.alternate:443",
7711 true,
7712 },
7713 };
7714
7715 session_deps_.use_alternate_protocols = true;
7716
7717 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
7718 session_deps_.proxy_service.reset(
7719 ProxyService::CreateFixed(tests[i].proxy_server));
7720 scoped_refptr<HttpNetworkSession> session(
7721 SetupSessionForGroupNameTests(GetParam(), &session_deps_));
7722
7723 HttpNetworkSessionPeer peer(session);
7724
7725 HostPortPair proxy_host("socks_proxy", 1080);
7726 CaptureGroupNameSOCKSSocketPool* socks_conn_pool =
7727 new CaptureGroupNameSOCKSSocketPool(NULL, NULL);
7728 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
7729 new CaptureGroupNameSSLSocketPool(NULL, NULL);
7730
7731 scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
7732 new MockClientSocketPoolManager);
7733 mock_pool_manager->SetSocketPoolForSOCKSProxy(proxy_host, socks_conn_pool);
7734 mock_pool_manager->SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
7735 peer.SetClientSocketPoolManager(
7736 mock_pool_manager.PassAs<ClientSocketPoolManager>());
7737
7738 scoped_ptr<HttpTransaction> trans(
7739 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7740
7741 EXPECT_EQ(ERR_IO_PENDING,
7742 GroupNameTransactionHelper(tests[i].url, session));
7743 if (tests[i].ssl)
7744 EXPECT_EQ(tests[i].expected_group_name,
7745 ssl_conn_pool->last_group_name_received());
7746 else
7747 EXPECT_EQ(tests[i].expected_group_name,
7748 socks_conn_pool->last_group_name_received());
7749 }
7750 }
7751
TEST_P(HttpNetworkTransactionTest,ReconsiderProxyAfterFailedConnection)7752 TEST_P(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
7753 HttpRequestInfo request;
7754 request.method = "GET";
7755 request.url = GURL("http://www.google.com/");
7756
7757 session_deps_.proxy_service.reset(
7758 ProxyService::CreateFixed("myproxy:70;foobar:80"));
7759
7760 // This simulates failure resolving all hostnames; that means we will fail
7761 // connecting to both proxies (myproxy:70 and foobar:80).
7762 session_deps_.host_resolver->rules()->AddSimulatedFailure("*");
7763
7764 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7765 scoped_ptr<HttpTransaction> trans(
7766 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
7767
7768 TestCompletionCallback callback;
7769
7770 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7771 EXPECT_EQ(ERR_IO_PENDING, rv);
7772
7773 rv = callback.WaitForResult();
7774 EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED, rv);
7775 }
7776
7777 // Base test to make sure that when the load flags for a request specify to
7778 // bypass the cache, the DNS cache is not used.
BypassHostCacheOnRefreshHelper(int load_flags)7779 void HttpNetworkTransactionTest::BypassHostCacheOnRefreshHelper(
7780 int load_flags) {
7781 // Issue a request, asking to bypass the cache(s).
7782 HttpRequestInfo request;
7783 request.method = "GET";
7784 request.load_flags = load_flags;
7785 request.url = GURL("http://www.google.com/");
7786
7787 // Select a host resolver that does caching.
7788 session_deps_.host_resolver.reset(new MockCachingHostResolver);
7789
7790 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7791 scoped_ptr<HttpTransaction> trans(
7792 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
7793
7794 // Warm up the host cache so it has an entry for "www.google.com".
7795 AddressList addrlist;
7796 TestCompletionCallback callback;
7797 int rv = session_deps_.host_resolver->Resolve(
7798 HostResolver::RequestInfo(HostPortPair("www.google.com", 80)),
7799 DEFAULT_PRIORITY,
7800 &addrlist,
7801 callback.callback(),
7802 NULL,
7803 BoundNetLog());
7804 EXPECT_EQ(ERR_IO_PENDING, rv);
7805 rv = callback.WaitForResult();
7806 EXPECT_EQ(OK, rv);
7807
7808 // Verify that it was added to host cache, by doing a subsequent async lookup
7809 // and confirming it completes synchronously.
7810 rv = session_deps_.host_resolver->Resolve(
7811 HostResolver::RequestInfo(HostPortPair("www.google.com", 80)),
7812 DEFAULT_PRIORITY,
7813 &addrlist,
7814 callback.callback(),
7815 NULL,
7816 BoundNetLog());
7817 ASSERT_EQ(OK, rv);
7818
7819 // Inject a failure the next time that "www.google.com" is resolved. This way
7820 // we can tell if the next lookup hit the cache, or the "network".
7821 // (cache --> success, "network" --> failure).
7822 session_deps_.host_resolver->rules()->AddSimulatedFailure("www.google.com");
7823
7824 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
7825 // first read -- this won't be reached as the host resolution will fail first.
7826 MockRead data_reads[] = { MockRead(SYNCHRONOUS, ERR_UNEXPECTED) };
7827 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
7828 session_deps_.socket_factory->AddSocketDataProvider(&data);
7829
7830 // Run the request.
7831 rv = trans->Start(&request, callback.callback(), BoundNetLog());
7832 ASSERT_EQ(ERR_IO_PENDING, rv);
7833 rv = callback.WaitForResult();
7834
7835 // If we bypassed the cache, we would have gotten a failure while resolving
7836 // "www.google.com".
7837 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
7838 }
7839
7840 // There are multiple load flags that should trigger the host cache bypass.
7841 // Test each in isolation:
TEST_P(HttpNetworkTransactionTest,BypassHostCacheOnRefresh1)7842 TEST_P(HttpNetworkTransactionTest, BypassHostCacheOnRefresh1) {
7843 BypassHostCacheOnRefreshHelper(LOAD_BYPASS_CACHE);
7844 }
7845
TEST_P(HttpNetworkTransactionTest,BypassHostCacheOnRefresh2)7846 TEST_P(HttpNetworkTransactionTest, BypassHostCacheOnRefresh2) {
7847 BypassHostCacheOnRefreshHelper(LOAD_VALIDATE_CACHE);
7848 }
7849
TEST_P(HttpNetworkTransactionTest,BypassHostCacheOnRefresh3)7850 TEST_P(HttpNetworkTransactionTest, BypassHostCacheOnRefresh3) {
7851 BypassHostCacheOnRefreshHelper(LOAD_DISABLE_CACHE);
7852 }
7853
7854 // Make sure we can handle an error when writing the request.
TEST_P(HttpNetworkTransactionTest,RequestWriteError)7855 TEST_P(HttpNetworkTransactionTest, RequestWriteError) {
7856 HttpRequestInfo request;
7857 request.method = "GET";
7858 request.url = GURL("http://www.foo.com/");
7859 request.load_flags = 0;
7860
7861 MockWrite write_failure[] = {
7862 MockWrite(ASYNC, ERR_CONNECTION_RESET),
7863 };
7864 StaticSocketDataProvider data(NULL, 0,
7865 write_failure, arraysize(write_failure));
7866 session_deps_.socket_factory->AddSocketDataProvider(&data);
7867 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7868
7869 TestCompletionCallback callback;
7870
7871 scoped_ptr<HttpTransaction> trans(
7872 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
7873
7874 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7875 EXPECT_EQ(ERR_IO_PENDING, rv);
7876
7877 rv = callback.WaitForResult();
7878 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
7879 }
7880
7881 // Check that a connection closed after the start of the headers finishes ok.
TEST_P(HttpNetworkTransactionTest,ConnectionClosedAfterStartOfHeaders)7882 TEST_P(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
7883 HttpRequestInfo request;
7884 request.method = "GET";
7885 request.url = GURL("http://www.foo.com/");
7886 request.load_flags = 0;
7887
7888 MockRead data_reads[] = {
7889 MockRead("HTTP/1."),
7890 MockRead(SYNCHRONOUS, OK),
7891 };
7892
7893 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
7894 session_deps_.socket_factory->AddSocketDataProvider(&data);
7895 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7896
7897 TestCompletionCallback callback;
7898
7899 scoped_ptr<HttpTransaction> trans(
7900 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
7901
7902 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7903 EXPECT_EQ(ERR_IO_PENDING, rv);
7904
7905 rv = callback.WaitForResult();
7906 EXPECT_EQ(OK, rv);
7907
7908 const HttpResponseInfo* response = trans->GetResponseInfo();
7909 ASSERT_TRUE(response != NULL);
7910
7911 EXPECT_TRUE(response->headers.get() != NULL);
7912 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
7913
7914 std::string response_data;
7915 rv = ReadTransaction(trans.get(), &response_data);
7916 EXPECT_EQ(OK, rv);
7917 EXPECT_EQ("", response_data);
7918 }
7919
7920 // Make sure that a dropped connection while draining the body for auth
7921 // restart does the right thing.
TEST_P(HttpNetworkTransactionTest,DrainResetOK)7922 TEST_P(HttpNetworkTransactionTest, DrainResetOK) {
7923 HttpRequestInfo request;
7924 request.method = "GET";
7925 request.url = GURL("http://www.google.com/");
7926 request.load_flags = 0;
7927
7928 MockWrite data_writes1[] = {
7929 MockWrite("GET / HTTP/1.1\r\n"
7930 "Host: www.google.com\r\n"
7931 "Connection: keep-alive\r\n\r\n"),
7932 };
7933
7934 MockRead data_reads1[] = {
7935 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
7936 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
7937 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7938 MockRead("Content-Length: 14\r\n\r\n"),
7939 MockRead("Unauth"),
7940 MockRead(ASYNC, ERR_CONNECTION_RESET),
7941 };
7942
7943 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
7944 data_writes1, arraysize(data_writes1));
7945 session_deps_.socket_factory->AddSocketDataProvider(&data1);
7946
7947 // After calling trans->RestartWithAuth(), this is the request we should
7948 // be issuing -- the final header line contains the credentials.
7949 MockWrite data_writes2[] = {
7950 MockWrite("GET / HTTP/1.1\r\n"
7951 "Host: www.google.com\r\n"
7952 "Connection: keep-alive\r\n"
7953 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
7954 };
7955
7956 // Lastly, the server responds with the actual content.
7957 MockRead data_reads2[] = {
7958 MockRead("HTTP/1.1 200 OK\r\n"),
7959 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7960 MockRead("Content-Length: 100\r\n\r\n"),
7961 MockRead(SYNCHRONOUS, OK),
7962 };
7963
7964 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
7965 data_writes2, arraysize(data_writes2));
7966 session_deps_.socket_factory->AddSocketDataProvider(&data2);
7967 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7968
7969 TestCompletionCallback callback1;
7970
7971 scoped_ptr<HttpTransaction> trans(
7972 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7973
7974 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
7975 EXPECT_EQ(ERR_IO_PENDING, rv);
7976
7977 rv = callback1.WaitForResult();
7978 EXPECT_EQ(OK, rv);
7979
7980 const HttpResponseInfo* response = trans->GetResponseInfo();
7981 ASSERT_TRUE(response != NULL);
7982 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
7983
7984 TestCompletionCallback callback2;
7985
7986 rv = trans->RestartWithAuth(
7987 AuthCredentials(kFoo, kBar), callback2.callback());
7988 EXPECT_EQ(ERR_IO_PENDING, rv);
7989
7990 rv = callback2.WaitForResult();
7991 EXPECT_EQ(OK, rv);
7992
7993 response = trans->GetResponseInfo();
7994 ASSERT_TRUE(response != NULL);
7995 EXPECT_TRUE(response->auth_challenge.get() == NULL);
7996 EXPECT_EQ(100, response->headers->GetContentLength());
7997 }
7998
7999 // Test HTTPS connections going through a proxy that sends extra data.
TEST_P(HttpNetworkTransactionTest,HTTPSViaProxyWithExtraData)8000 TEST_P(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
8001 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
8002
8003 HttpRequestInfo request;
8004 request.method = "GET";
8005 request.url = GURL("https://www.google.com/");
8006 request.load_flags = 0;
8007
8008 MockRead proxy_reads[] = {
8009 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
8010 MockRead(SYNCHRONOUS, OK)
8011 };
8012
8013 StaticSocketDataProvider data(proxy_reads, arraysize(proxy_reads), NULL, 0);
8014 SSLSocketDataProvider ssl(ASYNC, OK);
8015
8016 session_deps_.socket_factory->AddSocketDataProvider(&data);
8017 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
8018
8019 TestCompletionCallback callback;
8020
8021 session_deps_.socket_factory->ResetNextMockIndexes();
8022
8023 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8024 scoped_ptr<HttpTransaction> trans(
8025 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
8026
8027 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8028 EXPECT_EQ(ERR_IO_PENDING, rv);
8029
8030 rv = callback.WaitForResult();
8031 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
8032 }
8033
TEST_P(HttpNetworkTransactionTest,LargeContentLengthThenClose)8034 TEST_P(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
8035 HttpRequestInfo request;
8036 request.method = "GET";
8037 request.url = GURL("http://www.google.com/");
8038 request.load_flags = 0;
8039
8040 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8041 scoped_ptr<HttpTransaction> trans(
8042 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
8043
8044 MockRead data_reads[] = {
8045 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
8046 MockRead(SYNCHRONOUS, OK),
8047 };
8048
8049 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
8050 session_deps_.socket_factory->AddSocketDataProvider(&data);
8051
8052 TestCompletionCallback callback;
8053
8054 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8055 EXPECT_EQ(ERR_IO_PENDING, rv);
8056
8057 EXPECT_EQ(OK, callback.WaitForResult());
8058
8059 const HttpResponseInfo* response = trans->GetResponseInfo();
8060 ASSERT_TRUE(response != NULL);
8061
8062 EXPECT_TRUE(response->headers.get() != NULL);
8063 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
8064
8065 std::string response_data;
8066 rv = ReadTransaction(trans.get(), &response_data);
8067 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH, rv);
8068 }
8069
TEST_P(HttpNetworkTransactionTest,UploadFileSmallerThanLength)8070 TEST_P(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
8071 base::FilePath temp_file_path;
8072 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file_path));
8073 const uint64 kFakeSize = 100000; // file is actually blank
8074 UploadFileElementReader::ScopedOverridingContentLengthForTests
8075 overriding_content_length(kFakeSize);
8076
8077 ScopedVector<UploadElementReader> element_readers;
8078 element_readers.push_back(
8079 new UploadFileElementReader(base::MessageLoopProxy::current().get(),
8080 temp_file_path,
8081 0,
8082 kuint64max,
8083 base::Time()));
8084 UploadDataStream upload_data_stream(element_readers.Pass(), 0);
8085
8086 HttpRequestInfo request;
8087 request.method = "POST";
8088 request.url = GURL("http://www.google.com/upload");
8089 request.upload_data_stream = &upload_data_stream;
8090 request.load_flags = 0;
8091
8092 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8093 scoped_ptr<HttpTransaction> trans(
8094 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
8095
8096 MockRead data_reads[] = {
8097 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
8098 MockRead("hello world"),
8099 MockRead(SYNCHRONOUS, OK),
8100 };
8101 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
8102 session_deps_.socket_factory->AddSocketDataProvider(&data);
8103
8104 TestCompletionCallback callback;
8105
8106 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8107 EXPECT_EQ(ERR_IO_PENDING, rv);
8108
8109 rv = callback.WaitForResult();
8110 EXPECT_EQ(OK, rv);
8111
8112 const HttpResponseInfo* response = trans->GetResponseInfo();
8113 ASSERT_TRUE(response != NULL);
8114
8115 EXPECT_TRUE(response->headers.get() != NULL);
8116 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
8117
8118 std::string response_data;
8119 rv = ReadTransaction(trans.get(), &response_data);
8120 EXPECT_EQ(OK, rv);
8121 EXPECT_EQ("hello world", response_data);
8122
8123 base::DeleteFile(temp_file_path, false);
8124 }
8125
TEST_P(HttpNetworkTransactionTest,UploadUnreadableFile)8126 TEST_P(HttpNetworkTransactionTest, UploadUnreadableFile) {
8127 base::FilePath temp_file;
8128 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file));
8129 std::string temp_file_content("Unreadable file.");
8130 ASSERT_TRUE(base::WriteFile(temp_file, temp_file_content.c_str(),
8131 temp_file_content.length()));
8132 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
8133
8134 ScopedVector<UploadElementReader> element_readers;
8135 element_readers.push_back(
8136 new UploadFileElementReader(base::MessageLoopProxy::current().get(),
8137 temp_file,
8138 0,
8139 kuint64max,
8140 base::Time()));
8141 UploadDataStream upload_data_stream(element_readers.Pass(), 0);
8142
8143 HttpRequestInfo request;
8144 request.method = "POST";
8145 request.url = GURL("http://www.google.com/upload");
8146 request.upload_data_stream = &upload_data_stream;
8147 request.load_flags = 0;
8148
8149 // If we try to upload an unreadable file, the transaction should fail.
8150 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8151 scoped_ptr<HttpTransaction> trans(
8152 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
8153
8154 StaticSocketDataProvider data(NULL, 0, NULL, 0);
8155 session_deps_.socket_factory->AddSocketDataProvider(&data);
8156
8157 TestCompletionCallback callback;
8158
8159 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8160 EXPECT_EQ(ERR_IO_PENDING, rv);
8161
8162 rv = callback.WaitForResult();
8163 EXPECT_EQ(ERR_ACCESS_DENIED, rv);
8164
8165 const HttpResponseInfo* response = trans->GetResponseInfo();
8166 EXPECT_FALSE(response);
8167
8168 base::DeleteFile(temp_file, false);
8169 }
8170
TEST_P(HttpNetworkTransactionTest,CancelDuringInitRequestBody)8171 TEST_P(HttpNetworkTransactionTest, CancelDuringInitRequestBody) {
8172 class FakeUploadElementReader : public UploadElementReader {
8173 public:
8174 FakeUploadElementReader() {}
8175 virtual ~FakeUploadElementReader() {}
8176
8177 const CompletionCallback& callback() const { return callback_; }
8178
8179 // UploadElementReader overrides:
8180 virtual int Init(const CompletionCallback& callback) OVERRIDE {
8181 callback_ = callback;
8182 return ERR_IO_PENDING;
8183 }
8184 virtual uint64 GetContentLength() const OVERRIDE { return 0; }
8185 virtual uint64 BytesRemaining() const OVERRIDE { return 0; }
8186 virtual int Read(IOBuffer* buf,
8187 int buf_length,
8188 const CompletionCallback& callback) OVERRIDE {
8189 return ERR_FAILED;
8190 }
8191
8192 private:
8193 CompletionCallback callback_;
8194 };
8195
8196 FakeUploadElementReader* fake_reader = new FakeUploadElementReader;
8197 ScopedVector<UploadElementReader> element_readers;
8198 element_readers.push_back(fake_reader);
8199 UploadDataStream upload_data_stream(element_readers.Pass(), 0);
8200
8201 HttpRequestInfo request;
8202 request.method = "POST";
8203 request.url = GURL("http://www.google.com/upload");
8204 request.upload_data_stream = &upload_data_stream;
8205 request.load_flags = 0;
8206
8207 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8208 scoped_ptr<HttpTransaction> trans(
8209 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
8210
8211 StaticSocketDataProvider data;
8212 session_deps_.socket_factory->AddSocketDataProvider(&data);
8213
8214 TestCompletionCallback callback;
8215 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8216 EXPECT_EQ(ERR_IO_PENDING, rv);
8217 base::MessageLoop::current()->RunUntilIdle();
8218
8219 // Transaction is pending on request body initialization.
8220 ASSERT_FALSE(fake_reader->callback().is_null());
8221
8222 // Return Init()'s result after the transaction gets destroyed.
8223 trans.reset();
8224 fake_reader->callback().Run(OK); // Should not crash.
8225 }
8226
8227 // Tests that changes to Auth realms are treated like auth rejections.
TEST_P(HttpNetworkTransactionTest,ChangeAuthRealms)8228 TEST_P(HttpNetworkTransactionTest, ChangeAuthRealms) {
8229
8230 HttpRequestInfo request;
8231 request.method = "GET";
8232 request.url = GURL("http://www.google.com/");
8233 request.load_flags = 0;
8234
8235 // First transaction will request a resource and receive a Basic challenge
8236 // with realm="first_realm".
8237 MockWrite data_writes1[] = {
8238 MockWrite("GET / HTTP/1.1\r\n"
8239 "Host: www.google.com\r\n"
8240 "Connection: keep-alive\r\n"
8241 "\r\n"),
8242 };
8243 MockRead data_reads1[] = {
8244 MockRead("HTTP/1.1 401 Unauthorized\r\n"
8245 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
8246 "\r\n"),
8247 };
8248
8249 // After calling trans->RestartWithAuth(), provide an Authentication header
8250 // for first_realm. The server will reject and provide a challenge with
8251 // second_realm.
8252 MockWrite data_writes2[] = {
8253 MockWrite("GET / HTTP/1.1\r\n"
8254 "Host: www.google.com\r\n"
8255 "Connection: keep-alive\r\n"
8256 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
8257 "\r\n"),
8258 };
8259 MockRead data_reads2[] = {
8260 MockRead("HTTP/1.1 401 Unauthorized\r\n"
8261 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
8262 "\r\n"),
8263 };
8264
8265 // This again fails, and goes back to first_realm. Make sure that the
8266 // entry is removed from cache.
8267 MockWrite data_writes3[] = {
8268 MockWrite("GET / HTTP/1.1\r\n"
8269 "Host: www.google.com\r\n"
8270 "Connection: keep-alive\r\n"
8271 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
8272 "\r\n"),
8273 };
8274 MockRead data_reads3[] = {
8275 MockRead("HTTP/1.1 401 Unauthorized\r\n"
8276 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
8277 "\r\n"),
8278 };
8279
8280 // Try one last time (with the correct password) and get the resource.
8281 MockWrite data_writes4[] = {
8282 MockWrite("GET / HTTP/1.1\r\n"
8283 "Host: www.google.com\r\n"
8284 "Connection: keep-alive\r\n"
8285 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
8286 "\r\n"),
8287 };
8288 MockRead data_reads4[] = {
8289 MockRead("HTTP/1.1 200 OK\r\n"
8290 "Content-Type: text/html; charset=iso-8859-1\r\n"
8291 "Content-Length: 5\r\n"
8292 "\r\n"
8293 "hello"),
8294 };
8295
8296 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
8297 data_writes1, arraysize(data_writes1));
8298 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
8299 data_writes2, arraysize(data_writes2));
8300 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
8301 data_writes3, arraysize(data_writes3));
8302 StaticSocketDataProvider data4(data_reads4, arraysize(data_reads4),
8303 data_writes4, arraysize(data_writes4));
8304 session_deps_.socket_factory->AddSocketDataProvider(&data1);
8305 session_deps_.socket_factory->AddSocketDataProvider(&data2);
8306 session_deps_.socket_factory->AddSocketDataProvider(&data3);
8307 session_deps_.socket_factory->AddSocketDataProvider(&data4);
8308
8309 TestCompletionCallback callback1;
8310
8311 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8312 scoped_ptr<HttpTransaction> trans(
8313 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
8314
8315 // Issue the first request with Authorize headers. There should be a
8316 // password prompt for first_realm waiting to be filled in after the
8317 // transaction completes.
8318 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
8319 EXPECT_EQ(ERR_IO_PENDING, rv);
8320 rv = callback1.WaitForResult();
8321 EXPECT_EQ(OK, rv);
8322 const HttpResponseInfo* response = trans->GetResponseInfo();
8323 ASSERT_TRUE(response != NULL);
8324 const AuthChallengeInfo* challenge = response->auth_challenge.get();
8325 ASSERT_FALSE(challenge == NULL);
8326 EXPECT_FALSE(challenge->is_proxy);
8327 EXPECT_EQ("www.google.com:80", challenge->challenger.ToString());
8328 EXPECT_EQ("first_realm", challenge->realm);
8329 EXPECT_EQ("basic", challenge->scheme);
8330
8331 // Issue the second request with an incorrect password. There should be a
8332 // password prompt for second_realm waiting to be filled in after the
8333 // transaction completes.
8334 TestCompletionCallback callback2;
8335 rv = trans->RestartWithAuth(
8336 AuthCredentials(kFirst, kBaz), callback2.callback());
8337 EXPECT_EQ(ERR_IO_PENDING, rv);
8338 rv = callback2.WaitForResult();
8339 EXPECT_EQ(OK, rv);
8340 response = trans->GetResponseInfo();
8341 ASSERT_TRUE(response != NULL);
8342 challenge = response->auth_challenge.get();
8343 ASSERT_FALSE(challenge == NULL);
8344 EXPECT_FALSE(challenge->is_proxy);
8345 EXPECT_EQ("www.google.com:80", challenge->challenger.ToString());
8346 EXPECT_EQ("second_realm", challenge->realm);
8347 EXPECT_EQ("basic", challenge->scheme);
8348
8349 // Issue the third request with another incorrect password. There should be
8350 // a password prompt for first_realm waiting to be filled in. If the password
8351 // prompt is not present, it indicates that the HttpAuthCacheEntry for
8352 // first_realm was not correctly removed.
8353 TestCompletionCallback callback3;
8354 rv = trans->RestartWithAuth(
8355 AuthCredentials(kSecond, kFou), callback3.callback());
8356 EXPECT_EQ(ERR_IO_PENDING, rv);
8357 rv = callback3.WaitForResult();
8358 EXPECT_EQ(OK, rv);
8359 response = trans->GetResponseInfo();
8360 ASSERT_TRUE(response != NULL);
8361 challenge = response->auth_challenge.get();
8362 ASSERT_FALSE(challenge == NULL);
8363 EXPECT_FALSE(challenge->is_proxy);
8364 EXPECT_EQ("www.google.com:80", challenge->challenger.ToString());
8365 EXPECT_EQ("first_realm", challenge->realm);
8366 EXPECT_EQ("basic", challenge->scheme);
8367
8368 // Issue the fourth request with the correct password and username.
8369 TestCompletionCallback callback4;
8370 rv = trans->RestartWithAuth(
8371 AuthCredentials(kFirst, kBar), callback4.callback());
8372 EXPECT_EQ(ERR_IO_PENDING, rv);
8373 rv = callback4.WaitForResult();
8374 EXPECT_EQ(OK, rv);
8375 response = trans->GetResponseInfo();
8376 ASSERT_TRUE(response != NULL);
8377 EXPECT_TRUE(response->auth_challenge.get() == NULL);
8378 }
8379
TEST_P(HttpNetworkTransactionTest,HonorAlternateProtocolHeader)8380 TEST_P(HttpNetworkTransactionTest, HonorAlternateProtocolHeader) {
8381 session_deps_.next_protos = SpdyNextProtos();
8382 session_deps_.use_alternate_protocols = true;
8383
8384 std::string alternate_protocol_http_header =
8385 GetAlternateProtocolHttpHeader();
8386
8387 MockRead data_reads[] = {
8388 MockRead("HTTP/1.1 200 OK\r\n"),
8389 MockRead(alternate_protocol_http_header.c_str()),
8390 MockRead("hello world"),
8391 MockRead(SYNCHRONOUS, OK),
8392 };
8393
8394 HttpRequestInfo request;
8395 request.method = "GET";
8396 request.url = GURL("http://www.google.com/");
8397 request.load_flags = 0;
8398
8399 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
8400
8401 session_deps_.socket_factory->AddSocketDataProvider(&data);
8402
8403 TestCompletionCallback callback;
8404
8405 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8406 scoped_ptr<HttpTransaction> trans(
8407 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8408
8409 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8410 EXPECT_EQ(ERR_IO_PENDING, rv);
8411
8412 HostPortPair http_host_port_pair("www.google.com", 80);
8413 HttpServerProperties& http_server_properties =
8414 *session->http_server_properties();
8415 EXPECT_FALSE(
8416 http_server_properties.HasAlternateProtocol(http_host_port_pair));
8417
8418 EXPECT_EQ(OK, callback.WaitForResult());
8419
8420 const HttpResponseInfo* response = trans->GetResponseInfo();
8421 ASSERT_TRUE(response != NULL);
8422 ASSERT_TRUE(response->headers.get() != NULL);
8423 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8424 EXPECT_FALSE(response->was_fetched_via_spdy);
8425 EXPECT_FALSE(response->was_npn_negotiated);
8426
8427 std::string response_data;
8428 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8429 EXPECT_EQ("hello world", response_data);
8430
8431 ASSERT_TRUE(http_server_properties.HasAlternateProtocol(http_host_port_pair));
8432 const PortAlternateProtocolPair alternate =
8433 http_server_properties.GetAlternateProtocol(http_host_port_pair);
8434 PortAlternateProtocolPair expected_alternate;
8435 expected_alternate.port = 443;
8436 expected_alternate.protocol = AlternateProtocolFromNextProto(GetParam());
8437 EXPECT_TRUE(expected_alternate.Equals(alternate));
8438 }
8439
TEST_P(HttpNetworkTransactionTest,MarkBrokenAlternateProtocolAndFallback)8440 TEST_P(HttpNetworkTransactionTest,
8441 MarkBrokenAlternateProtocolAndFallback) {
8442 session_deps_.use_alternate_protocols = true;
8443
8444 HttpRequestInfo request;
8445 request.method = "GET";
8446 request.url = GURL("http://www.google.com/");
8447 request.load_flags = 0;
8448
8449 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
8450 StaticSocketDataProvider first_data;
8451 first_data.set_connect_data(mock_connect);
8452 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
8453
8454 MockRead data_reads[] = {
8455 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8456 MockRead("hello world"),
8457 MockRead(ASYNC, OK),
8458 };
8459 StaticSocketDataProvider second_data(
8460 data_reads, arraysize(data_reads), NULL, 0);
8461 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
8462
8463 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8464
8465 base::WeakPtr<HttpServerProperties> http_server_properties =
8466 session->http_server_properties();
8467 // Port must be < 1024, or the header will be ignored (since initial port was
8468 // port 80 (another restricted port).
8469 http_server_properties->SetAlternateProtocol(
8470 HostPortPair::FromURL(request.url),
8471 666 /* port is ignored by MockConnect anyway */,
8472 AlternateProtocolFromNextProto(GetParam()));
8473
8474 scoped_ptr<HttpTransaction> trans(
8475 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8476 TestCompletionCallback callback;
8477
8478 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8479 EXPECT_EQ(ERR_IO_PENDING, rv);
8480 EXPECT_EQ(OK, callback.WaitForResult());
8481
8482 const HttpResponseInfo* response = trans->GetResponseInfo();
8483 ASSERT_TRUE(response != NULL);
8484 ASSERT_TRUE(response->headers.get() != NULL);
8485 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8486
8487 std::string response_data;
8488 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8489 EXPECT_EQ("hello world", response_data);
8490
8491 ASSERT_TRUE(http_server_properties->HasAlternateProtocol(
8492 HostPortPair::FromURL(request.url)));
8493 const PortAlternateProtocolPair alternate =
8494 http_server_properties->GetAlternateProtocol(
8495 HostPortPair::FromURL(request.url));
8496 EXPECT_EQ(ALTERNATE_PROTOCOL_BROKEN, alternate.protocol);
8497 }
8498
TEST_P(HttpNetworkTransactionTest,AlternateProtocolPortRestrictedBlocked)8499 TEST_P(HttpNetworkTransactionTest,
8500 AlternateProtocolPortRestrictedBlocked) {
8501 // Ensure that we're not allowed to redirect traffic via an alternate
8502 // protocol to an unrestricted (port >= 1024) when the original traffic was
8503 // on a restricted port (port < 1024). Ensure that we can redirect in all
8504 // other cases.
8505 session_deps_.use_alternate_protocols = true;
8506
8507 HttpRequestInfo restricted_port_request;
8508 restricted_port_request.method = "GET";
8509 restricted_port_request.url = GURL("http://www.google.com:1023/");
8510 restricted_port_request.load_flags = 0;
8511
8512 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
8513 StaticSocketDataProvider first_data;
8514 first_data.set_connect_data(mock_connect);
8515 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
8516
8517 MockRead data_reads[] = {
8518 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8519 MockRead("hello world"),
8520 MockRead(ASYNC, OK),
8521 };
8522 StaticSocketDataProvider second_data(
8523 data_reads, arraysize(data_reads), NULL, 0);
8524 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
8525
8526 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8527
8528 base::WeakPtr<HttpServerProperties> http_server_properties =
8529 session->http_server_properties();
8530 const int kUnrestrictedAlternatePort = 1024;
8531 http_server_properties->SetAlternateProtocol(
8532 HostPortPair::FromURL(restricted_port_request.url),
8533 kUnrestrictedAlternatePort,
8534 AlternateProtocolFromNextProto(GetParam()));
8535
8536 scoped_ptr<HttpTransaction> trans(
8537 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8538 TestCompletionCallback callback;
8539
8540 int rv = trans->Start(
8541 &restricted_port_request,
8542 callback.callback(), BoundNetLog());
8543 EXPECT_EQ(ERR_IO_PENDING, rv);
8544 // Invalid change to unrestricted port should fail.
8545 EXPECT_EQ(ERR_CONNECTION_REFUSED, callback.WaitForResult());
8546 }
8547
TEST_P(HttpNetworkTransactionTest,AlternateProtocolPortRestrictedPermitted)8548 TEST_P(HttpNetworkTransactionTest,
8549 AlternateProtocolPortRestrictedPermitted) {
8550 // Ensure that we're allowed to redirect traffic via an alternate
8551 // protocol to an unrestricted (port >= 1024) when the original traffic was
8552 // on a restricted port (port < 1024) if we set
8553 // enable_user_alternate_protocol_ports.
8554
8555 session_deps_.use_alternate_protocols = true;
8556 session_deps_.enable_user_alternate_protocol_ports = true;
8557
8558 HttpRequestInfo restricted_port_request;
8559 restricted_port_request.method = "GET";
8560 restricted_port_request.url = GURL("http://www.google.com:1023/");
8561 restricted_port_request.load_flags = 0;
8562
8563 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
8564 StaticSocketDataProvider first_data;
8565 first_data.set_connect_data(mock_connect);
8566 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
8567
8568 MockRead data_reads[] = {
8569 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8570 MockRead("hello world"),
8571 MockRead(ASYNC, OK),
8572 };
8573 StaticSocketDataProvider second_data(
8574 data_reads, arraysize(data_reads), NULL, 0);
8575 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
8576
8577 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8578
8579 base::WeakPtr<HttpServerProperties> http_server_properties =
8580 session->http_server_properties();
8581 const int kUnrestrictedAlternatePort = 1024;
8582 http_server_properties->SetAlternateProtocol(
8583 HostPortPair::FromURL(restricted_port_request.url),
8584 kUnrestrictedAlternatePort,
8585 AlternateProtocolFromNextProto(GetParam()));
8586
8587 scoped_ptr<HttpTransaction> trans(
8588 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8589 TestCompletionCallback callback;
8590
8591 EXPECT_EQ(ERR_IO_PENDING, trans->Start(
8592 &restricted_port_request,
8593 callback.callback(), BoundNetLog()));
8594 // Change to unrestricted port should succeed.
8595 EXPECT_EQ(OK, callback.WaitForResult());
8596 }
8597
TEST_P(HttpNetworkTransactionTest,AlternateProtocolPortRestrictedAllowed)8598 TEST_P(HttpNetworkTransactionTest,
8599 AlternateProtocolPortRestrictedAllowed) {
8600 // Ensure that we're not allowed to redirect traffic via an alternate
8601 // protocol to an unrestricted (port >= 1024) when the original traffic was
8602 // on a restricted port (port < 1024). Ensure that we can redirect in all
8603 // other cases.
8604 session_deps_.use_alternate_protocols = true;
8605
8606 HttpRequestInfo restricted_port_request;
8607 restricted_port_request.method = "GET";
8608 restricted_port_request.url = GURL("http://www.google.com:1023/");
8609 restricted_port_request.load_flags = 0;
8610
8611 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
8612 StaticSocketDataProvider first_data;
8613 first_data.set_connect_data(mock_connect);
8614 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
8615
8616 MockRead data_reads[] = {
8617 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8618 MockRead("hello world"),
8619 MockRead(ASYNC, OK),
8620 };
8621 StaticSocketDataProvider second_data(
8622 data_reads, arraysize(data_reads), NULL, 0);
8623 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
8624
8625 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8626
8627 base::WeakPtr<HttpServerProperties> http_server_properties =
8628 session->http_server_properties();
8629 const int kRestrictedAlternatePort = 80;
8630 http_server_properties->SetAlternateProtocol(
8631 HostPortPair::FromURL(restricted_port_request.url),
8632 kRestrictedAlternatePort,
8633 AlternateProtocolFromNextProto(GetParam()));
8634
8635 scoped_ptr<HttpTransaction> trans(
8636 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8637 TestCompletionCallback callback;
8638
8639 int rv = trans->Start(
8640 &restricted_port_request,
8641 callback.callback(), BoundNetLog());
8642 EXPECT_EQ(ERR_IO_PENDING, rv);
8643 // Valid change to restricted port should pass.
8644 EXPECT_EQ(OK, callback.WaitForResult());
8645 }
8646
TEST_P(HttpNetworkTransactionTest,AlternateProtocolPortUnrestrictedAllowed1)8647 TEST_P(HttpNetworkTransactionTest,
8648 AlternateProtocolPortUnrestrictedAllowed1) {
8649 // Ensure that we're not allowed to redirect traffic via an alternate
8650 // protocol to an unrestricted (port >= 1024) when the original traffic was
8651 // on a restricted port (port < 1024). Ensure that we can redirect in all
8652 // other cases.
8653 session_deps_.use_alternate_protocols = true;
8654
8655 HttpRequestInfo unrestricted_port_request;
8656 unrestricted_port_request.method = "GET";
8657 unrestricted_port_request.url = GURL("http://www.google.com:1024/");
8658 unrestricted_port_request.load_flags = 0;
8659
8660 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
8661 StaticSocketDataProvider first_data;
8662 first_data.set_connect_data(mock_connect);
8663 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
8664
8665 MockRead data_reads[] = {
8666 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8667 MockRead("hello world"),
8668 MockRead(ASYNC, OK),
8669 };
8670 StaticSocketDataProvider second_data(
8671 data_reads, arraysize(data_reads), NULL, 0);
8672 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
8673
8674 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8675
8676 base::WeakPtr<HttpServerProperties> http_server_properties =
8677 session->http_server_properties();
8678 const int kRestrictedAlternatePort = 80;
8679 http_server_properties->SetAlternateProtocol(
8680 HostPortPair::FromURL(unrestricted_port_request.url),
8681 kRestrictedAlternatePort,
8682 AlternateProtocolFromNextProto(GetParam()));
8683
8684 scoped_ptr<HttpTransaction> trans(
8685 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8686 TestCompletionCallback callback;
8687
8688 int rv = trans->Start(
8689 &unrestricted_port_request, callback.callback(), BoundNetLog());
8690 EXPECT_EQ(ERR_IO_PENDING, rv);
8691 // Valid change to restricted port should pass.
8692 EXPECT_EQ(OK, callback.WaitForResult());
8693 }
8694
TEST_P(HttpNetworkTransactionTest,AlternateProtocolPortUnrestrictedAllowed2)8695 TEST_P(HttpNetworkTransactionTest,
8696 AlternateProtocolPortUnrestrictedAllowed2) {
8697 // Ensure that we're not allowed to redirect traffic via an alternate
8698 // protocol to an unrestricted (port >= 1024) when the original traffic was
8699 // on a restricted port (port < 1024). Ensure that we can redirect in all
8700 // other cases.
8701 session_deps_.use_alternate_protocols = true;
8702
8703 HttpRequestInfo unrestricted_port_request;
8704 unrestricted_port_request.method = "GET";
8705 unrestricted_port_request.url = GURL("http://www.google.com:1024/");
8706 unrestricted_port_request.load_flags = 0;
8707
8708 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
8709 StaticSocketDataProvider first_data;
8710 first_data.set_connect_data(mock_connect);
8711 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
8712
8713 MockRead data_reads[] = {
8714 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8715 MockRead("hello world"),
8716 MockRead(ASYNC, OK),
8717 };
8718 StaticSocketDataProvider second_data(
8719 data_reads, arraysize(data_reads), NULL, 0);
8720 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
8721
8722 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8723
8724 base::WeakPtr<HttpServerProperties> http_server_properties =
8725 session->http_server_properties();
8726 const int kUnrestrictedAlternatePort = 1024;
8727 http_server_properties->SetAlternateProtocol(
8728 HostPortPair::FromURL(unrestricted_port_request.url),
8729 kUnrestrictedAlternatePort,
8730 AlternateProtocolFromNextProto(GetParam()));
8731
8732 scoped_ptr<HttpTransaction> trans(
8733 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8734 TestCompletionCallback callback;
8735
8736 int rv = trans->Start(
8737 &unrestricted_port_request, callback.callback(), BoundNetLog());
8738 EXPECT_EQ(ERR_IO_PENDING, rv);
8739 // Valid change to an unrestricted port should pass.
8740 EXPECT_EQ(OK, callback.WaitForResult());
8741 }
8742
TEST_P(HttpNetworkTransactionTest,AlternateProtocolUnsafeBlocked)8743 TEST_P(HttpNetworkTransactionTest, AlternateProtocolUnsafeBlocked) {
8744 // Ensure that we're not allowed to redirect traffic via an alternate
8745 // protocol to an unsafe port, and that we resume the second
8746 // HttpStreamFactoryImpl::Job once the alternate protocol request fails.
8747 session_deps_.use_alternate_protocols = true;
8748
8749 HttpRequestInfo request;
8750 request.method = "GET";
8751 request.url = GURL("http://www.google.com/");
8752 request.load_flags = 0;
8753
8754 // The alternate protocol request will error out before we attempt to connect,
8755 // so only the standard HTTP request will try to connect.
8756 MockRead data_reads[] = {
8757 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8758 MockRead("hello world"),
8759 MockRead(ASYNC, OK),
8760 };
8761 StaticSocketDataProvider data(
8762 data_reads, arraysize(data_reads), NULL, 0);
8763 session_deps_.socket_factory->AddSocketDataProvider(&data);
8764
8765 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8766
8767 base::WeakPtr<HttpServerProperties> http_server_properties =
8768 session->http_server_properties();
8769 const int kUnsafePort = 7;
8770 http_server_properties->SetAlternateProtocol(
8771 HostPortPair::FromURL(request.url),
8772 kUnsafePort,
8773 AlternateProtocolFromNextProto(GetParam()));
8774
8775 scoped_ptr<HttpTransaction> trans(
8776 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8777 TestCompletionCallback callback;
8778
8779 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8780 EXPECT_EQ(ERR_IO_PENDING, rv);
8781 // The HTTP request should succeed.
8782 EXPECT_EQ(OK, callback.WaitForResult());
8783
8784 // Disable alternate protocol before the asserts.
8785 // HttpStreamFactory::set_use_alternate_protocols(false);
8786
8787 const HttpResponseInfo* response = trans->GetResponseInfo();
8788 ASSERT_TRUE(response != NULL);
8789 ASSERT_TRUE(response->headers.get() != NULL);
8790 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8791
8792 std::string response_data;
8793 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8794 EXPECT_EQ("hello world", response_data);
8795 }
8796
TEST_P(HttpNetworkTransactionTest,UseAlternateProtocolForNpnSpdy)8797 TEST_P(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) {
8798 session_deps_.use_alternate_protocols = true;
8799 session_deps_.next_protos = SpdyNextProtos();
8800
8801 HttpRequestInfo request;
8802 request.method = "GET";
8803 request.url = GURL("http://www.google.com/");
8804 request.load_flags = 0;
8805
8806 std::string alternate_protocol_http_header =
8807 GetAlternateProtocolHttpHeader();
8808
8809 MockRead data_reads[] = {
8810 MockRead("HTTP/1.1 200 OK\r\n"),
8811 MockRead(alternate_protocol_http_header.c_str()),
8812 MockRead("hello world"),
8813 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
8814 MockRead(ASYNC, OK)
8815 };
8816
8817 StaticSocketDataProvider first_transaction(
8818 data_reads, arraysize(data_reads), NULL, 0);
8819 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
8820
8821 SSLSocketDataProvider ssl(ASYNC, OK);
8822 ssl.SetNextProto(GetParam());
8823 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
8824
8825 scoped_ptr<SpdyFrame> req(
8826 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
8827 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
8828
8829 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
8830 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
8831 MockRead spdy_reads[] = {
8832 CreateMockRead(*resp),
8833 CreateMockRead(*data),
8834 MockRead(ASYNC, 0, 0),
8835 };
8836
8837 DelayedSocketData spdy_data(
8838 1, // wait for one write to finish before reading.
8839 spdy_reads, arraysize(spdy_reads),
8840 spdy_writes, arraysize(spdy_writes));
8841 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
8842
8843 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
8844 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
8845 NULL, 0, NULL, 0);
8846 hanging_non_alternate_protocol_socket.set_connect_data(
8847 never_finishing_connect);
8848 session_deps_.socket_factory->AddSocketDataProvider(
8849 &hanging_non_alternate_protocol_socket);
8850
8851 TestCompletionCallback callback;
8852
8853 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8854 scoped_ptr<HttpTransaction> trans(
8855 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8856
8857 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8858 EXPECT_EQ(ERR_IO_PENDING, rv);
8859 EXPECT_EQ(OK, callback.WaitForResult());
8860
8861 const HttpResponseInfo* response = trans->GetResponseInfo();
8862 ASSERT_TRUE(response != NULL);
8863 ASSERT_TRUE(response->headers.get() != NULL);
8864 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8865
8866 std::string response_data;
8867 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8868 EXPECT_EQ("hello world", response_data);
8869
8870 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8871
8872 rv = trans->Start(&request, callback.callback(), BoundNetLog());
8873 EXPECT_EQ(ERR_IO_PENDING, rv);
8874 EXPECT_EQ(OK, callback.WaitForResult());
8875
8876 response = trans->GetResponseInfo();
8877 ASSERT_TRUE(response != NULL);
8878 ASSERT_TRUE(response->headers.get() != NULL);
8879 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8880 EXPECT_TRUE(response->was_fetched_via_spdy);
8881 EXPECT_TRUE(response->was_npn_negotiated);
8882
8883 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8884 EXPECT_EQ("hello!", response_data);
8885 }
8886
TEST_P(HttpNetworkTransactionTest,AlternateProtocolWithSpdyLateBinding)8887 TEST_P(HttpNetworkTransactionTest, AlternateProtocolWithSpdyLateBinding) {
8888 session_deps_.use_alternate_protocols = true;
8889 session_deps_.next_protos = SpdyNextProtos();
8890
8891 HttpRequestInfo request;
8892 request.method = "GET";
8893 request.url = GURL("http://www.google.com/");
8894 request.load_flags = 0;
8895
8896 std::string alternate_protocol_http_header =
8897 GetAlternateProtocolHttpHeader();
8898
8899 MockRead data_reads[] = {
8900 MockRead("HTTP/1.1 200 OK\r\n"),
8901 MockRead(alternate_protocol_http_header.c_str()),
8902 MockRead("hello world"),
8903 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
8904 MockRead(ASYNC, OK),
8905 };
8906
8907 StaticSocketDataProvider first_transaction(
8908 data_reads, arraysize(data_reads), NULL, 0);
8909 // Socket 1 is the HTTP transaction with the Alternate-Protocol header.
8910 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
8911
8912 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
8913 StaticSocketDataProvider hanging_socket(
8914 NULL, 0, NULL, 0);
8915 hanging_socket.set_connect_data(never_finishing_connect);
8916 // Socket 2 and 3 are the hanging Alternate-Protocol and
8917 // non-Alternate-Protocol jobs from the 2nd transaction.
8918 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket);
8919 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket);
8920
8921 SSLSocketDataProvider ssl(ASYNC, OK);
8922 ssl.SetNextProto(GetParam());
8923 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
8924
8925 scoped_ptr<SpdyFrame> req1(
8926 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
8927 scoped_ptr<SpdyFrame> req2(
8928 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
8929 MockWrite spdy_writes[] = {
8930 CreateMockWrite(*req1),
8931 CreateMockWrite(*req2),
8932 };
8933 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
8934 scoped_ptr<SpdyFrame> data1(spdy_util_.ConstructSpdyBodyFrame(1, true));
8935 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
8936 scoped_ptr<SpdyFrame> data2(spdy_util_.ConstructSpdyBodyFrame(3, true));
8937 MockRead spdy_reads[] = {
8938 CreateMockRead(*resp1),
8939 CreateMockRead(*data1),
8940 CreateMockRead(*resp2),
8941 CreateMockRead(*data2),
8942 MockRead(ASYNC, 0, 0),
8943 };
8944
8945 DelayedSocketData spdy_data(
8946 2, // wait for writes to finish before reading.
8947 spdy_reads, arraysize(spdy_reads),
8948 spdy_writes, arraysize(spdy_writes));
8949 // Socket 4 is the successful Alternate-Protocol for transaction 3.
8950 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
8951
8952 // Socket 5 is the unsuccessful non-Alternate-Protocol for transaction 3.
8953 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket);
8954
8955 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8956 TestCompletionCallback callback1;
8957 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
8958
8959 int rv = trans1.Start(&request, callback1.callback(), BoundNetLog());
8960 EXPECT_EQ(ERR_IO_PENDING, rv);
8961 EXPECT_EQ(OK, callback1.WaitForResult());
8962
8963 const HttpResponseInfo* response = trans1.GetResponseInfo();
8964 ASSERT_TRUE(response != NULL);
8965 ASSERT_TRUE(response->headers.get() != NULL);
8966 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8967
8968 std::string response_data;
8969 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
8970 EXPECT_EQ("hello world", response_data);
8971
8972 TestCompletionCallback callback2;
8973 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
8974 rv = trans2.Start(&request, callback2.callback(), BoundNetLog());
8975 EXPECT_EQ(ERR_IO_PENDING, rv);
8976
8977 TestCompletionCallback callback3;
8978 HttpNetworkTransaction trans3(DEFAULT_PRIORITY, session.get());
8979 rv = trans3.Start(&request, callback3.callback(), BoundNetLog());
8980 EXPECT_EQ(ERR_IO_PENDING, rv);
8981
8982 EXPECT_EQ(OK, callback2.WaitForResult());
8983 EXPECT_EQ(OK, callback3.WaitForResult());
8984
8985 response = trans2.GetResponseInfo();
8986 ASSERT_TRUE(response != NULL);
8987 ASSERT_TRUE(response->headers.get() != NULL);
8988 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8989 EXPECT_TRUE(response->was_fetched_via_spdy);
8990 EXPECT_TRUE(response->was_npn_negotiated);
8991 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
8992 EXPECT_EQ("hello!", response_data);
8993
8994 response = trans3.GetResponseInfo();
8995 ASSERT_TRUE(response != NULL);
8996 ASSERT_TRUE(response->headers.get() != NULL);
8997 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8998 EXPECT_TRUE(response->was_fetched_via_spdy);
8999 EXPECT_TRUE(response->was_npn_negotiated);
9000 ASSERT_EQ(OK, ReadTransaction(&trans3, &response_data));
9001 EXPECT_EQ("hello!", response_data);
9002 }
9003
TEST_P(HttpNetworkTransactionTest,StallAlternateProtocolForNpnSpdy)9004 TEST_P(HttpNetworkTransactionTest, StallAlternateProtocolForNpnSpdy) {
9005 session_deps_.use_alternate_protocols = true;
9006 session_deps_.next_protos = SpdyNextProtos();
9007
9008 HttpRequestInfo request;
9009 request.method = "GET";
9010 request.url = GURL("http://www.google.com/");
9011 request.load_flags = 0;
9012
9013 std::string alternate_protocol_http_header =
9014 GetAlternateProtocolHttpHeader();
9015
9016 MockRead data_reads[] = {
9017 MockRead("HTTP/1.1 200 OK\r\n"),
9018 MockRead(alternate_protocol_http_header.c_str()),
9019 MockRead("hello world"),
9020 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
9021 MockRead(ASYNC, OK),
9022 };
9023
9024 StaticSocketDataProvider first_transaction(
9025 data_reads, arraysize(data_reads), NULL, 0);
9026 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
9027
9028 SSLSocketDataProvider ssl(ASYNC, OK);
9029 ssl.SetNextProto(GetParam());
9030 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9031
9032 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
9033 StaticSocketDataProvider hanging_alternate_protocol_socket(
9034 NULL, 0, NULL, 0);
9035 hanging_alternate_protocol_socket.set_connect_data(
9036 never_finishing_connect);
9037 session_deps_.socket_factory->AddSocketDataProvider(
9038 &hanging_alternate_protocol_socket);
9039
9040 // 2nd request is just a copy of the first one, over HTTP again.
9041 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
9042
9043 TestCompletionCallback callback;
9044
9045 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9046 scoped_ptr<HttpTransaction> trans(
9047 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9048
9049 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9050 EXPECT_EQ(ERR_IO_PENDING, rv);
9051 EXPECT_EQ(OK, callback.WaitForResult());
9052
9053 const HttpResponseInfo* response = trans->GetResponseInfo();
9054 ASSERT_TRUE(response != NULL);
9055 ASSERT_TRUE(response->headers.get() != NULL);
9056 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9057
9058 std::string response_data;
9059 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9060 EXPECT_EQ("hello world", response_data);
9061
9062 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9063
9064 rv = trans->Start(&request, callback.callback(), BoundNetLog());
9065 EXPECT_EQ(ERR_IO_PENDING, rv);
9066 EXPECT_EQ(OK, callback.WaitForResult());
9067
9068 response = trans->GetResponseInfo();
9069 ASSERT_TRUE(response != NULL);
9070 ASSERT_TRUE(response->headers.get() != NULL);
9071 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9072 EXPECT_FALSE(response->was_fetched_via_spdy);
9073 EXPECT_FALSE(response->was_npn_negotiated);
9074
9075 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9076 EXPECT_EQ("hello world", response_data);
9077 }
9078
9079 class CapturingProxyResolver : public ProxyResolver {
9080 public:
CapturingProxyResolver()9081 CapturingProxyResolver() : ProxyResolver(false /* expects_pac_bytes */) {}
~CapturingProxyResolver()9082 virtual ~CapturingProxyResolver() {}
9083
GetProxyForURL(const GURL & url,ProxyInfo * results,const CompletionCallback & callback,RequestHandle * request,const BoundNetLog & net_log)9084 virtual int GetProxyForURL(const GURL& url,
9085 ProxyInfo* results,
9086 const CompletionCallback& callback,
9087 RequestHandle* request,
9088 const BoundNetLog& net_log) OVERRIDE {
9089 ProxyServer proxy_server(ProxyServer::SCHEME_HTTP,
9090 HostPortPair("myproxy", 80));
9091 results->UseProxyServer(proxy_server);
9092 resolved_.push_back(url);
9093 return OK;
9094 }
9095
CancelRequest(RequestHandle request)9096 virtual void CancelRequest(RequestHandle request) OVERRIDE {
9097 NOTREACHED();
9098 }
9099
GetLoadState(RequestHandle request) const9100 virtual LoadState GetLoadState(RequestHandle request) const OVERRIDE {
9101 NOTREACHED();
9102 return LOAD_STATE_IDLE;
9103 }
9104
CancelSetPacScript()9105 virtual void CancelSetPacScript() OVERRIDE {
9106 NOTREACHED();
9107 }
9108
SetPacScript(const scoped_refptr<ProxyResolverScriptData> &,const CompletionCallback &)9109 virtual int SetPacScript(const scoped_refptr<ProxyResolverScriptData>&,
9110 const CompletionCallback& /*callback*/) OVERRIDE {
9111 return OK;
9112 }
9113
resolved() const9114 const std::vector<GURL>& resolved() const { return resolved_; }
9115
9116 private:
9117 std::vector<GURL> resolved_;
9118
9119 DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver);
9120 };
9121
TEST_P(HttpNetworkTransactionTest,UseAlternateProtocolForTunneledNpnSpdy)9122 TEST_P(HttpNetworkTransactionTest,
9123 UseAlternateProtocolForTunneledNpnSpdy) {
9124 session_deps_.use_alternate_protocols = true;
9125 session_deps_.next_protos = SpdyNextProtos();
9126
9127 ProxyConfig proxy_config;
9128 proxy_config.set_auto_detect(true);
9129 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
9130
9131 CapturingProxyResolver* capturing_proxy_resolver =
9132 new CapturingProxyResolver();
9133 session_deps_.proxy_service.reset(new ProxyService(
9134 new ProxyConfigServiceFixed(proxy_config), capturing_proxy_resolver,
9135 NULL));
9136 CapturingNetLog net_log;
9137 session_deps_.net_log = &net_log;
9138
9139 HttpRequestInfo request;
9140 request.method = "GET";
9141 request.url = GURL("http://www.google.com/");
9142 request.load_flags = 0;
9143
9144 std::string alternate_protocol_http_header =
9145 GetAlternateProtocolHttpHeader();
9146
9147 MockRead data_reads[] = {
9148 MockRead("HTTP/1.1 200 OK\r\n"),
9149 MockRead(alternate_protocol_http_header.c_str()),
9150 MockRead("hello world"),
9151 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
9152 MockRead(ASYNC, OK),
9153 };
9154
9155 StaticSocketDataProvider first_transaction(
9156 data_reads, arraysize(data_reads), NULL, 0);
9157 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
9158
9159 SSLSocketDataProvider ssl(ASYNC, OK);
9160 ssl.SetNextProto(GetParam());
9161 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9162
9163 scoped_ptr<SpdyFrame> req(
9164 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
9165 MockWrite spdy_writes[] = {
9166 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
9167 "Host: www.google.com\r\n"
9168 "Proxy-Connection: keep-alive\r\n\r\n"), // 0
9169 CreateMockWrite(*req), // 3
9170 };
9171
9172 const char kCONNECTResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
9173
9174 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
9175 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
9176 MockRead spdy_reads[] = {
9177 MockRead(ASYNC, kCONNECTResponse, arraysize(kCONNECTResponse) - 1, 1), // 1
9178 CreateMockRead(*resp.get(), 4), // 2, 4
9179 CreateMockRead(*data.get(), 4), // 5
9180 MockRead(ASYNC, 0, 0, 4), // 6
9181 };
9182
9183 OrderedSocketData spdy_data(
9184 spdy_reads, arraysize(spdy_reads),
9185 spdy_writes, arraysize(spdy_writes));
9186 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
9187
9188 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
9189 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
9190 NULL, 0, NULL, 0);
9191 hanging_non_alternate_protocol_socket.set_connect_data(
9192 never_finishing_connect);
9193 session_deps_.socket_factory->AddSocketDataProvider(
9194 &hanging_non_alternate_protocol_socket);
9195
9196 TestCompletionCallback callback;
9197
9198 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9199 scoped_ptr<HttpTransaction> trans(
9200 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9201
9202 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9203 EXPECT_EQ(ERR_IO_PENDING, rv);
9204 EXPECT_EQ(OK, callback.WaitForResult());
9205
9206 const HttpResponseInfo* response = trans->GetResponseInfo();
9207 ASSERT_TRUE(response != NULL);
9208 ASSERT_TRUE(response->headers.get() != NULL);
9209 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9210 EXPECT_FALSE(response->was_fetched_via_spdy);
9211 EXPECT_FALSE(response->was_npn_negotiated);
9212
9213 std::string response_data;
9214 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9215 EXPECT_EQ("hello world", response_data);
9216
9217 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9218
9219 rv = trans->Start(&request, callback.callback(), BoundNetLog());
9220 EXPECT_EQ(ERR_IO_PENDING, rv);
9221 EXPECT_EQ(OK, callback.WaitForResult());
9222
9223 response = trans->GetResponseInfo();
9224 ASSERT_TRUE(response != NULL);
9225 ASSERT_TRUE(response->headers.get() != NULL);
9226 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9227 EXPECT_TRUE(response->was_fetched_via_spdy);
9228 EXPECT_TRUE(response->was_npn_negotiated);
9229
9230 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9231 EXPECT_EQ("hello!", response_data);
9232 ASSERT_EQ(3u, capturing_proxy_resolver->resolved().size());
9233 EXPECT_EQ("http://www.google.com/",
9234 capturing_proxy_resolver->resolved()[0].spec());
9235 EXPECT_EQ("https://www.google.com/",
9236 capturing_proxy_resolver->resolved()[1].spec());
9237
9238 LoadTimingInfo load_timing_info;
9239 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
9240 TestLoadTimingNotReusedWithPac(load_timing_info,
9241 CONNECT_TIMING_HAS_SSL_TIMES);
9242 }
9243
TEST_P(HttpNetworkTransactionTest,UseAlternateProtocolForNpnSpdyWithExistingSpdySession)9244 TEST_P(HttpNetworkTransactionTest,
9245 UseAlternateProtocolForNpnSpdyWithExistingSpdySession) {
9246 session_deps_.use_alternate_protocols = true;
9247 session_deps_.next_protos = SpdyNextProtos();
9248
9249 HttpRequestInfo request;
9250 request.method = "GET";
9251 request.url = GURL("http://www.google.com/");
9252 request.load_flags = 0;
9253
9254 std::string alternate_protocol_http_header =
9255 GetAlternateProtocolHttpHeader();
9256
9257 MockRead data_reads[] = {
9258 MockRead("HTTP/1.1 200 OK\r\n"),
9259 MockRead(alternate_protocol_http_header.c_str()),
9260 MockRead("hello world"),
9261 MockRead(ASYNC, OK),
9262 };
9263
9264 StaticSocketDataProvider first_transaction(
9265 data_reads, arraysize(data_reads), NULL, 0);
9266 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
9267
9268 SSLSocketDataProvider ssl(ASYNC, OK);
9269 ssl.SetNextProto(GetParam());
9270 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9271
9272 scoped_ptr<SpdyFrame> req(
9273 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
9274 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
9275
9276 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
9277 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
9278 MockRead spdy_reads[] = {
9279 CreateMockRead(*resp),
9280 CreateMockRead(*data),
9281 MockRead(ASYNC, 0, 0),
9282 };
9283
9284 DelayedSocketData spdy_data(
9285 1, // wait for one write to finish before reading.
9286 spdy_reads, arraysize(spdy_reads),
9287 spdy_writes, arraysize(spdy_writes));
9288 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
9289
9290 TestCompletionCallback callback;
9291
9292 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9293
9294 scoped_ptr<HttpTransaction> trans(
9295 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9296
9297 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9298 EXPECT_EQ(ERR_IO_PENDING, rv);
9299 EXPECT_EQ(OK, callback.WaitForResult());
9300
9301 const HttpResponseInfo* response = trans->GetResponseInfo();
9302 ASSERT_TRUE(response != NULL);
9303 ASSERT_TRUE(response->headers.get() != NULL);
9304 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9305
9306 std::string response_data;
9307 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9308 EXPECT_EQ("hello world", response_data);
9309
9310 // Set up an initial SpdySession in the pool to reuse.
9311 HostPortPair host_port_pair("www.google.com", 443);
9312 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
9313 PRIVACY_MODE_DISABLED);
9314 base::WeakPtr<SpdySession> spdy_session =
9315 CreateSecureSpdySession(session, key, BoundNetLog());
9316
9317 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9318
9319 rv = trans->Start(&request, callback.callback(), BoundNetLog());
9320 EXPECT_EQ(ERR_IO_PENDING, rv);
9321 EXPECT_EQ(OK, callback.WaitForResult());
9322
9323 response = trans->GetResponseInfo();
9324 ASSERT_TRUE(response != NULL);
9325 ASSERT_TRUE(response->headers.get() != NULL);
9326 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9327 EXPECT_TRUE(response->was_fetched_via_spdy);
9328 EXPECT_TRUE(response->was_npn_negotiated);
9329
9330 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9331 EXPECT_EQ("hello!", response_data);
9332 }
9333
9334 // GenerateAuthToken is a mighty big test.
9335 // It tests all permutation of GenerateAuthToken behavior:
9336 // - Synchronous and Asynchronous completion.
9337 // - OK or error on completion.
9338 // - Direct connection, non-authenticating proxy, and authenticating proxy.
9339 // - HTTP or HTTPS backend (to include proxy tunneling).
9340 // - Non-authenticating and authenticating backend.
9341 //
9342 // In all, there are 44 reasonable permuations (for example, if there are
9343 // problems generating an auth token for an authenticating proxy, we don't
9344 // need to test all permutations of the backend server).
9345 //
9346 // The test proceeds by going over each of the configuration cases, and
9347 // potentially running up to three rounds in each of the tests. The TestConfig
9348 // specifies both the configuration for the test as well as the expectations
9349 // for the results.
TEST_P(HttpNetworkTransactionTest,GenerateAuthToken)9350 TEST_P(HttpNetworkTransactionTest, GenerateAuthToken) {
9351 static const char kServer[] = "http://www.example.com";
9352 static const char kSecureServer[] = "https://www.example.com";
9353 static const char kProxy[] = "myproxy:70";
9354 const int kAuthErr = ERR_INVALID_AUTH_CREDENTIALS;
9355
9356 enum AuthTiming {
9357 AUTH_NONE,
9358 AUTH_SYNC,
9359 AUTH_ASYNC,
9360 };
9361
9362 const MockWrite kGet(
9363 "GET / HTTP/1.1\r\n"
9364 "Host: www.example.com\r\n"
9365 "Connection: keep-alive\r\n\r\n");
9366 const MockWrite kGetProxy(
9367 "GET http://www.example.com/ HTTP/1.1\r\n"
9368 "Host: www.example.com\r\n"
9369 "Proxy-Connection: keep-alive\r\n\r\n");
9370 const MockWrite kGetAuth(
9371 "GET / HTTP/1.1\r\n"
9372 "Host: www.example.com\r\n"
9373 "Connection: keep-alive\r\n"
9374 "Authorization: auth_token\r\n\r\n");
9375 const MockWrite kGetProxyAuth(
9376 "GET http://www.example.com/ HTTP/1.1\r\n"
9377 "Host: www.example.com\r\n"
9378 "Proxy-Connection: keep-alive\r\n"
9379 "Proxy-Authorization: auth_token\r\n\r\n");
9380 const MockWrite kGetAuthThroughProxy(
9381 "GET http://www.example.com/ HTTP/1.1\r\n"
9382 "Host: www.example.com\r\n"
9383 "Proxy-Connection: keep-alive\r\n"
9384 "Authorization: auth_token\r\n\r\n");
9385 const MockWrite kGetAuthWithProxyAuth(
9386 "GET http://www.example.com/ HTTP/1.1\r\n"
9387 "Host: www.example.com\r\n"
9388 "Proxy-Connection: keep-alive\r\n"
9389 "Proxy-Authorization: auth_token\r\n"
9390 "Authorization: auth_token\r\n\r\n");
9391 const MockWrite kConnect(
9392 "CONNECT www.example.com:443 HTTP/1.1\r\n"
9393 "Host: www.example.com\r\n"
9394 "Proxy-Connection: keep-alive\r\n\r\n");
9395 const MockWrite kConnectProxyAuth(
9396 "CONNECT www.example.com:443 HTTP/1.1\r\n"
9397 "Host: www.example.com\r\n"
9398 "Proxy-Connection: keep-alive\r\n"
9399 "Proxy-Authorization: auth_token\r\n\r\n");
9400
9401 const MockRead kSuccess(
9402 "HTTP/1.1 200 OK\r\n"
9403 "Content-Type: text/html; charset=iso-8859-1\r\n"
9404 "Content-Length: 3\r\n\r\n"
9405 "Yes");
9406 const MockRead kFailure(
9407 "Should not be called.");
9408 const MockRead kServerChallenge(
9409 "HTTP/1.1 401 Unauthorized\r\n"
9410 "WWW-Authenticate: Mock realm=server\r\n"
9411 "Content-Type: text/html; charset=iso-8859-1\r\n"
9412 "Content-Length: 14\r\n\r\n"
9413 "Unauthorized\r\n");
9414 const MockRead kProxyChallenge(
9415 "HTTP/1.1 407 Unauthorized\r\n"
9416 "Proxy-Authenticate: Mock realm=proxy\r\n"
9417 "Proxy-Connection: close\r\n"
9418 "Content-Type: text/html; charset=iso-8859-1\r\n"
9419 "Content-Length: 14\r\n\r\n"
9420 "Unauthorized\r\n");
9421 const MockRead kProxyConnected(
9422 "HTTP/1.1 200 Connection Established\r\n\r\n");
9423
9424 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
9425 // no constructors, but the C++ compiler on Windows warns about
9426 // unspecified data in compound literals. So, moved to using constructors,
9427 // and TestRound's created with the default constructor should not be used.
9428 struct TestRound {
9429 TestRound()
9430 : expected_rv(ERR_UNEXPECTED),
9431 extra_write(NULL),
9432 extra_read(NULL) {
9433 }
9434 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
9435 int expected_rv_arg)
9436 : write(write_arg),
9437 read(read_arg),
9438 expected_rv(expected_rv_arg),
9439 extra_write(NULL),
9440 extra_read(NULL) {
9441 }
9442 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
9443 int expected_rv_arg, const MockWrite* extra_write_arg,
9444 const MockRead* extra_read_arg)
9445 : write(write_arg),
9446 read(read_arg),
9447 expected_rv(expected_rv_arg),
9448 extra_write(extra_write_arg),
9449 extra_read(extra_read_arg) {
9450 }
9451 MockWrite write;
9452 MockRead read;
9453 int expected_rv;
9454 const MockWrite* extra_write;
9455 const MockRead* extra_read;
9456 };
9457
9458 static const int kNoSSL = 500;
9459
9460 struct TestConfig {
9461 const char* proxy_url;
9462 AuthTiming proxy_auth_timing;
9463 int proxy_auth_rv;
9464 const char* server_url;
9465 AuthTiming server_auth_timing;
9466 int server_auth_rv;
9467 int num_auth_rounds;
9468 int first_ssl_round;
9469 TestRound rounds[3];
9470 } test_configs[] = {
9471 // Non-authenticating HTTP server with a direct connection.
9472 { NULL, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
9473 { TestRound(kGet, kSuccess, OK)}},
9474 // Authenticating HTTP server with a direct connection.
9475 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
9476 { TestRound(kGet, kServerChallenge, OK),
9477 TestRound(kGetAuth, kSuccess, OK)}},
9478 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
9479 { TestRound(kGet, kServerChallenge, OK),
9480 TestRound(kGetAuth, kFailure, kAuthErr)}},
9481 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
9482 { TestRound(kGet, kServerChallenge, OK),
9483 TestRound(kGetAuth, kSuccess, OK)}},
9484 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
9485 { TestRound(kGet, kServerChallenge, OK),
9486 TestRound(kGetAuth, kFailure, kAuthErr)}},
9487 // Non-authenticating HTTP server through a non-authenticating proxy.
9488 { kProxy, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
9489 { TestRound(kGetProxy, kSuccess, OK)}},
9490 // Authenticating HTTP server through a non-authenticating proxy.
9491 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
9492 { TestRound(kGetProxy, kServerChallenge, OK),
9493 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
9494 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
9495 { TestRound(kGetProxy, kServerChallenge, OK),
9496 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
9497 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
9498 { TestRound(kGetProxy, kServerChallenge, OK),
9499 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
9500 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
9501 { TestRound(kGetProxy, kServerChallenge, OK),
9502 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
9503 // Non-authenticating HTTP server through an authenticating proxy.
9504 { kProxy, AUTH_SYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
9505 { TestRound(kGetProxy, kProxyChallenge, OK),
9506 TestRound(kGetProxyAuth, kSuccess, OK)}},
9507 { kProxy, AUTH_SYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
9508 { TestRound(kGetProxy, kProxyChallenge, OK),
9509 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
9510 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
9511 { TestRound(kGetProxy, kProxyChallenge, OK),
9512 TestRound(kGetProxyAuth, kSuccess, OK)}},
9513 { kProxy, AUTH_ASYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
9514 { TestRound(kGetProxy, kProxyChallenge, OK),
9515 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
9516 // Authenticating HTTP server through an authenticating proxy.
9517 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
9518 { TestRound(kGetProxy, kProxyChallenge, OK),
9519 TestRound(kGetProxyAuth, kServerChallenge, OK),
9520 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
9521 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
9522 { TestRound(kGetProxy, kProxyChallenge, OK),
9523 TestRound(kGetProxyAuth, kServerChallenge, OK),
9524 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
9525 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
9526 { TestRound(kGetProxy, kProxyChallenge, OK),
9527 TestRound(kGetProxyAuth, kServerChallenge, OK),
9528 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
9529 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
9530 { TestRound(kGetProxy, kProxyChallenge, OK),
9531 TestRound(kGetProxyAuth, kServerChallenge, OK),
9532 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
9533 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
9534 { TestRound(kGetProxy, kProxyChallenge, OK),
9535 TestRound(kGetProxyAuth, kServerChallenge, OK),
9536 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
9537 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
9538 { TestRound(kGetProxy, kProxyChallenge, OK),
9539 TestRound(kGetProxyAuth, kServerChallenge, OK),
9540 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
9541 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
9542 { TestRound(kGetProxy, kProxyChallenge, OK),
9543 TestRound(kGetProxyAuth, kServerChallenge, OK),
9544 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
9545 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
9546 { TestRound(kGetProxy, kProxyChallenge, OK),
9547 TestRound(kGetProxyAuth, kServerChallenge, OK),
9548 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
9549 // Non-authenticating HTTPS server with a direct connection.
9550 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
9551 { TestRound(kGet, kSuccess, OK)}},
9552 // Authenticating HTTPS server with a direct connection.
9553 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
9554 { TestRound(kGet, kServerChallenge, OK),
9555 TestRound(kGetAuth, kSuccess, OK)}},
9556 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
9557 { TestRound(kGet, kServerChallenge, OK),
9558 TestRound(kGetAuth, kFailure, kAuthErr)}},
9559 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
9560 { TestRound(kGet, kServerChallenge, OK),
9561 TestRound(kGetAuth, kSuccess, OK)}},
9562 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
9563 { TestRound(kGet, kServerChallenge, OK),
9564 TestRound(kGetAuth, kFailure, kAuthErr)}},
9565 // Non-authenticating HTTPS server with a non-authenticating proxy.
9566 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
9567 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
9568 // Authenticating HTTPS server through a non-authenticating proxy.
9569 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
9570 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
9571 TestRound(kGetAuth, kSuccess, OK)}},
9572 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
9573 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
9574 TestRound(kGetAuth, kFailure, kAuthErr)}},
9575 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
9576 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
9577 TestRound(kGetAuth, kSuccess, OK)}},
9578 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
9579 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
9580 TestRound(kGetAuth, kFailure, kAuthErr)}},
9581 // Non-Authenticating HTTPS server through an authenticating proxy.
9582 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
9583 { TestRound(kConnect, kProxyChallenge, OK),
9584 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
9585 { kProxy, AUTH_SYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
9586 { TestRound(kConnect, kProxyChallenge, OK),
9587 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
9588 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
9589 { TestRound(kConnect, kProxyChallenge, OK),
9590 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
9591 { kProxy, AUTH_ASYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
9592 { TestRound(kConnect, kProxyChallenge, OK),
9593 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
9594 // Authenticating HTTPS server through an authenticating proxy.
9595 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
9596 { TestRound(kConnect, kProxyChallenge, OK),
9597 TestRound(kConnectProxyAuth, kProxyConnected, OK,
9598 &kGet, &kServerChallenge),
9599 TestRound(kGetAuth, kSuccess, OK)}},
9600 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
9601 { TestRound(kConnect, kProxyChallenge, OK),
9602 TestRound(kConnectProxyAuth, kProxyConnected, OK,
9603 &kGet, &kServerChallenge),
9604 TestRound(kGetAuth, kFailure, kAuthErr)}},
9605 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
9606 { TestRound(kConnect, kProxyChallenge, OK),
9607 TestRound(kConnectProxyAuth, kProxyConnected, OK,
9608 &kGet, &kServerChallenge),
9609 TestRound(kGetAuth, kSuccess, OK)}},
9610 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
9611 { TestRound(kConnect, kProxyChallenge, OK),
9612 TestRound(kConnectProxyAuth, kProxyConnected, OK,
9613 &kGet, &kServerChallenge),
9614 TestRound(kGetAuth, kFailure, kAuthErr)}},
9615 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
9616 { TestRound(kConnect, kProxyChallenge, OK),
9617 TestRound(kConnectProxyAuth, kProxyConnected, OK,
9618 &kGet, &kServerChallenge),
9619 TestRound(kGetAuth, kSuccess, OK)}},
9620 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
9621 { TestRound(kConnect, kProxyChallenge, OK),
9622 TestRound(kConnectProxyAuth, kProxyConnected, OK,
9623 &kGet, &kServerChallenge),
9624 TestRound(kGetAuth, kFailure, kAuthErr)}},
9625 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
9626 { TestRound(kConnect, kProxyChallenge, OK),
9627 TestRound(kConnectProxyAuth, kProxyConnected, OK,
9628 &kGet, &kServerChallenge),
9629 TestRound(kGetAuth, kSuccess, OK)}},
9630 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
9631 { TestRound(kConnect, kProxyChallenge, OK),
9632 TestRound(kConnectProxyAuth, kProxyConnected, OK,
9633 &kGet, &kServerChallenge),
9634 TestRound(kGetAuth, kFailure, kAuthErr)}},
9635 };
9636
9637 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_configs); ++i) {
9638 HttpAuthHandlerMock::Factory* auth_factory(
9639 new HttpAuthHandlerMock::Factory());
9640 session_deps_.http_auth_handler_factory.reset(auth_factory);
9641 const TestConfig& test_config = test_configs[i];
9642
9643 // Set up authentication handlers as necessary.
9644 if (test_config.proxy_auth_timing != AUTH_NONE) {
9645 for (int n = 0; n < 2; n++) {
9646 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
9647 std::string auth_challenge = "Mock realm=proxy";
9648 GURL origin(test_config.proxy_url);
9649 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
9650 auth_challenge.end());
9651 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_PROXY,
9652 origin, BoundNetLog());
9653 auth_handler->SetGenerateExpectation(
9654 test_config.proxy_auth_timing == AUTH_ASYNC,
9655 test_config.proxy_auth_rv);
9656 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_PROXY);
9657 }
9658 }
9659 if (test_config.server_auth_timing != AUTH_NONE) {
9660 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
9661 std::string auth_challenge = "Mock realm=server";
9662 GURL origin(test_config.server_url);
9663 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
9664 auth_challenge.end());
9665 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
9666 origin, BoundNetLog());
9667 auth_handler->SetGenerateExpectation(
9668 test_config.server_auth_timing == AUTH_ASYNC,
9669 test_config.server_auth_rv);
9670 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
9671 }
9672 if (test_config.proxy_url) {
9673 session_deps_.proxy_service.reset(
9674 ProxyService::CreateFixed(test_config.proxy_url));
9675 } else {
9676 session_deps_.proxy_service.reset(ProxyService::CreateDirect());
9677 }
9678
9679 HttpRequestInfo request;
9680 request.method = "GET";
9681 request.url = GURL(test_config.server_url);
9682 request.load_flags = 0;
9683
9684 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9685 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session);
9686
9687 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
9688 const TestRound& read_write_round = test_config.rounds[round];
9689
9690 // Set up expected reads and writes.
9691 MockRead reads[2];
9692 reads[0] = read_write_round.read;
9693 size_t length_reads = 1;
9694 if (read_write_round.extra_read) {
9695 reads[1] = *read_write_round.extra_read;
9696 length_reads = 2;
9697 }
9698
9699 MockWrite writes[2];
9700 writes[0] = read_write_round.write;
9701 size_t length_writes = 1;
9702 if (read_write_round.extra_write) {
9703 writes[1] = *read_write_round.extra_write;
9704 length_writes = 2;
9705 }
9706 StaticSocketDataProvider data_provider(
9707 reads, length_reads, writes, length_writes);
9708 session_deps_.socket_factory->AddSocketDataProvider(&data_provider);
9709
9710 // Add an SSL sequence if necessary.
9711 SSLSocketDataProvider ssl_socket_data_provider(SYNCHRONOUS, OK);
9712 if (round >= test_config.first_ssl_round)
9713 session_deps_.socket_factory->AddSSLSocketDataProvider(
9714 &ssl_socket_data_provider);
9715
9716 // Start or restart the transaction.
9717 TestCompletionCallback callback;
9718 int rv;
9719 if (round == 0) {
9720 rv = trans.Start(&request, callback.callback(), BoundNetLog());
9721 } else {
9722 rv = trans.RestartWithAuth(
9723 AuthCredentials(kFoo, kBar), callback.callback());
9724 }
9725 if (rv == ERR_IO_PENDING)
9726 rv = callback.WaitForResult();
9727
9728 // Compare results with expected data.
9729 EXPECT_EQ(read_write_round.expected_rv, rv);
9730 const HttpResponseInfo* response = trans.GetResponseInfo();
9731 if (read_write_round.expected_rv == OK) {
9732 ASSERT_TRUE(response != NULL);
9733 } else {
9734 EXPECT_TRUE(response == NULL);
9735 EXPECT_EQ(round + 1, test_config.num_auth_rounds);
9736 continue;
9737 }
9738 if (round + 1 < test_config.num_auth_rounds) {
9739 EXPECT_FALSE(response->auth_challenge.get() == NULL);
9740 } else {
9741 EXPECT_TRUE(response->auth_challenge.get() == NULL);
9742 }
9743 }
9744 }
9745 }
9746
TEST_P(HttpNetworkTransactionTest,MultiRoundAuth)9747 TEST_P(HttpNetworkTransactionTest, MultiRoundAuth) {
9748 // Do multi-round authentication and make sure it works correctly.
9749 HttpAuthHandlerMock::Factory* auth_factory(
9750 new HttpAuthHandlerMock::Factory());
9751 session_deps_.http_auth_handler_factory.reset(auth_factory);
9752 session_deps_.proxy_service.reset(ProxyService::CreateDirect());
9753 session_deps_.host_resolver->rules()->AddRule("www.example.com", "10.0.0.1");
9754 session_deps_.host_resolver->set_synchronous_mode(true);
9755
9756 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
9757 auth_handler->set_connection_based(true);
9758 std::string auth_challenge = "Mock realm=server";
9759 GURL origin("http://www.example.com");
9760 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
9761 auth_challenge.end());
9762 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
9763 origin, BoundNetLog());
9764 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
9765
9766 int rv = OK;
9767 const HttpResponseInfo* response = NULL;
9768 HttpRequestInfo request;
9769 request.method = "GET";
9770 request.url = origin;
9771 request.load_flags = 0;
9772
9773 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9774
9775 // Use a TCP Socket Pool with only one connection per group. This is used
9776 // to validate that the TCP socket is not released to the pool between
9777 // each round of multi-round authentication.
9778 HttpNetworkSessionPeer session_peer(session);
9779 ClientSocketPoolHistograms transport_pool_histograms("SmallTCP");
9780 TransportClientSocketPool* transport_pool = new TransportClientSocketPool(
9781 50, // Max sockets for pool
9782 1, // Max sockets per group
9783 &transport_pool_histograms,
9784 session_deps_.host_resolver.get(),
9785 session_deps_.socket_factory.get(),
9786 session_deps_.net_log);
9787 scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
9788 new MockClientSocketPoolManager);
9789 mock_pool_manager->SetTransportSocketPool(transport_pool);
9790 session_peer.SetClientSocketPoolManager(
9791 mock_pool_manager.PassAs<ClientSocketPoolManager>());
9792
9793 scoped_ptr<HttpTransaction> trans(
9794 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9795 TestCompletionCallback callback;
9796
9797 const MockWrite kGet(
9798 "GET / HTTP/1.1\r\n"
9799 "Host: www.example.com\r\n"
9800 "Connection: keep-alive\r\n\r\n");
9801 const MockWrite kGetAuth(
9802 "GET / HTTP/1.1\r\n"
9803 "Host: www.example.com\r\n"
9804 "Connection: keep-alive\r\n"
9805 "Authorization: auth_token\r\n\r\n");
9806
9807 const MockRead kServerChallenge(
9808 "HTTP/1.1 401 Unauthorized\r\n"
9809 "WWW-Authenticate: Mock realm=server\r\n"
9810 "Content-Type: text/html; charset=iso-8859-1\r\n"
9811 "Content-Length: 14\r\n\r\n"
9812 "Unauthorized\r\n");
9813 const MockRead kSuccess(
9814 "HTTP/1.1 200 OK\r\n"
9815 "Content-Type: text/html; charset=iso-8859-1\r\n"
9816 "Content-Length: 3\r\n\r\n"
9817 "Yes");
9818
9819 MockWrite writes[] = {
9820 // First round
9821 kGet,
9822 // Second round
9823 kGetAuth,
9824 // Third round
9825 kGetAuth,
9826 // Fourth round
9827 kGetAuth,
9828 // Competing request
9829 kGet,
9830 };
9831 MockRead reads[] = {
9832 // First round
9833 kServerChallenge,
9834 // Second round
9835 kServerChallenge,
9836 // Third round
9837 kServerChallenge,
9838 // Fourth round
9839 kSuccess,
9840 // Competing response
9841 kSuccess,
9842 };
9843 StaticSocketDataProvider data_provider(reads, arraysize(reads),
9844 writes, arraysize(writes));
9845 session_deps_.socket_factory->AddSocketDataProvider(&data_provider);
9846
9847 const char* const kSocketGroup = "www.example.com:80";
9848
9849 // First round of authentication.
9850 auth_handler->SetGenerateExpectation(false, OK);
9851 rv = trans->Start(&request, callback.callback(), BoundNetLog());
9852 if (rv == ERR_IO_PENDING)
9853 rv = callback.WaitForResult();
9854 EXPECT_EQ(OK, rv);
9855 response = trans->GetResponseInfo();
9856 ASSERT_TRUE(response != NULL);
9857 EXPECT_FALSE(response->auth_challenge.get() == NULL);
9858 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
9859
9860 // In between rounds, another request comes in for the same domain.
9861 // It should not be able to grab the TCP socket that trans has already
9862 // claimed.
9863 scoped_ptr<HttpTransaction> trans_compete(
9864 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9865 TestCompletionCallback callback_compete;
9866 rv = trans_compete->Start(
9867 &request, callback_compete.callback(), BoundNetLog());
9868 EXPECT_EQ(ERR_IO_PENDING, rv);
9869 // callback_compete.WaitForResult at this point would stall forever,
9870 // since the HttpNetworkTransaction does not release the request back to
9871 // the pool until after authentication completes.
9872
9873 // Second round of authentication.
9874 auth_handler->SetGenerateExpectation(false, OK);
9875 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
9876 if (rv == ERR_IO_PENDING)
9877 rv = callback.WaitForResult();
9878 EXPECT_EQ(OK, rv);
9879 response = trans->GetResponseInfo();
9880 ASSERT_TRUE(response != NULL);
9881 EXPECT_TRUE(response->auth_challenge.get() == NULL);
9882 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
9883
9884 // Third round of authentication.
9885 auth_handler->SetGenerateExpectation(false, OK);
9886 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
9887 if (rv == ERR_IO_PENDING)
9888 rv = callback.WaitForResult();
9889 EXPECT_EQ(OK, rv);
9890 response = trans->GetResponseInfo();
9891 ASSERT_TRUE(response != NULL);
9892 EXPECT_TRUE(response->auth_challenge.get() == NULL);
9893 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
9894
9895 // Fourth round of authentication, which completes successfully.
9896 auth_handler->SetGenerateExpectation(false, OK);
9897 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
9898 if (rv == ERR_IO_PENDING)
9899 rv = callback.WaitForResult();
9900 EXPECT_EQ(OK, rv);
9901 response = trans->GetResponseInfo();
9902 ASSERT_TRUE(response != NULL);
9903 EXPECT_TRUE(response->auth_challenge.get() == NULL);
9904 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
9905
9906 // Read the body since the fourth round was successful. This will also
9907 // release the socket back to the pool.
9908 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(50));
9909 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
9910 if (rv == ERR_IO_PENDING)
9911 rv = callback.WaitForResult();
9912 EXPECT_EQ(3, rv);
9913 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
9914 EXPECT_EQ(0, rv);
9915 // There are still 0 idle sockets, since the trans_compete transaction
9916 // will be handed it immediately after trans releases it to the group.
9917 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
9918
9919 // The competing request can now finish. Wait for the headers and then
9920 // read the body.
9921 rv = callback_compete.WaitForResult();
9922 EXPECT_EQ(OK, rv);
9923 rv = trans_compete->Read(io_buf.get(), io_buf->size(), callback.callback());
9924 if (rv == ERR_IO_PENDING)
9925 rv = callback.WaitForResult();
9926 EXPECT_EQ(3, rv);
9927 rv = trans_compete->Read(io_buf.get(), io_buf->size(), callback.callback());
9928 EXPECT_EQ(0, rv);
9929
9930 // Finally, the socket is released to the group.
9931 EXPECT_EQ(1, transport_pool->IdleSocketCountInGroup(kSocketGroup));
9932 }
9933
9934 // This tests the case that a request is issued via http instead of spdy after
9935 // npn is negotiated.
TEST_P(HttpNetworkTransactionTest,NpnWithHttpOverSSL)9936 TEST_P(HttpNetworkTransactionTest, NpnWithHttpOverSSL) {
9937 session_deps_.use_alternate_protocols = true;
9938 NextProtoVector next_protos;
9939 next_protos.push_back(kProtoHTTP11);
9940 session_deps_.next_protos = next_protos;
9941
9942 HttpRequestInfo request;
9943 request.method = "GET";
9944 request.url = GURL("https://www.google.com/");
9945 request.load_flags = 0;
9946
9947 MockWrite data_writes[] = {
9948 MockWrite("GET / HTTP/1.1\r\n"
9949 "Host: www.google.com\r\n"
9950 "Connection: keep-alive\r\n\r\n"),
9951 };
9952
9953 std::string alternate_protocol_http_header =
9954 GetAlternateProtocolHttpHeader();
9955
9956 MockRead data_reads[] = {
9957 MockRead("HTTP/1.1 200 OK\r\n"),
9958 MockRead(alternate_protocol_http_header.c_str()),
9959 MockRead("hello world"),
9960 MockRead(SYNCHRONOUS, OK),
9961 };
9962
9963 SSLSocketDataProvider ssl(ASYNC, OK);
9964 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
9965 ssl.next_proto = "http/1.1";
9966 ssl.protocol_negotiated = kProtoHTTP11;
9967
9968 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9969
9970 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
9971 data_writes, arraysize(data_writes));
9972 session_deps_.socket_factory->AddSocketDataProvider(&data);
9973
9974 TestCompletionCallback callback;
9975
9976 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9977 scoped_ptr<HttpTransaction> trans(
9978 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9979
9980 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9981
9982 EXPECT_EQ(ERR_IO_PENDING, rv);
9983 EXPECT_EQ(OK, callback.WaitForResult());
9984
9985 const HttpResponseInfo* response = trans->GetResponseInfo();
9986 ASSERT_TRUE(response != NULL);
9987 ASSERT_TRUE(response->headers.get() != NULL);
9988 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9989
9990 std::string response_data;
9991 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9992 EXPECT_EQ("hello world", response_data);
9993
9994 EXPECT_FALSE(response->was_fetched_via_spdy);
9995 EXPECT_TRUE(response->was_npn_negotiated);
9996 }
9997
TEST_P(HttpNetworkTransactionTest,SpdyPostNPNServerHangup)9998 TEST_P(HttpNetworkTransactionTest, SpdyPostNPNServerHangup) {
9999 // Simulate the SSL handshake completing with an NPN negotiation
10000 // followed by an immediate server closing of the socket.
10001 // Fix crash: http://crbug.com/46369
10002 session_deps_.use_alternate_protocols = true;
10003 session_deps_.next_protos = SpdyNextProtos();
10004
10005 HttpRequestInfo request;
10006 request.method = "GET";
10007 request.url = GURL("https://www.google.com/");
10008 request.load_flags = 0;
10009
10010 SSLSocketDataProvider ssl(ASYNC, OK);
10011 ssl.SetNextProto(GetParam());
10012 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10013
10014 scoped_ptr<SpdyFrame> req(
10015 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
10016 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
10017
10018 MockRead spdy_reads[] = {
10019 MockRead(SYNCHRONOUS, 0, 0) // Not async - return 0 immediately.
10020 };
10021
10022 DelayedSocketData spdy_data(
10023 0, // don't wait in this case, immediate hangup.
10024 spdy_reads, arraysize(spdy_reads),
10025 spdy_writes, arraysize(spdy_writes));
10026 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
10027
10028 TestCompletionCallback callback;
10029
10030 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10031 scoped_ptr<HttpTransaction> trans(
10032 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10033
10034 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
10035 EXPECT_EQ(ERR_IO_PENDING, rv);
10036 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback.WaitForResult());
10037 }
10038
10039 // A subclass of HttpAuthHandlerMock that records the request URL when
10040 // it gets it. This is needed since the auth handler may get destroyed
10041 // before we get a chance to query it.
10042 class UrlRecordingHttpAuthHandlerMock : public HttpAuthHandlerMock {
10043 public:
UrlRecordingHttpAuthHandlerMock(GURL * url)10044 explicit UrlRecordingHttpAuthHandlerMock(GURL* url) : url_(url) {}
10045
~UrlRecordingHttpAuthHandlerMock()10046 virtual ~UrlRecordingHttpAuthHandlerMock() {}
10047
10048 protected:
GenerateAuthTokenImpl(const AuthCredentials * credentials,const HttpRequestInfo * request,const CompletionCallback & callback,std::string * auth_token)10049 virtual int GenerateAuthTokenImpl(const AuthCredentials* credentials,
10050 const HttpRequestInfo* request,
10051 const CompletionCallback& callback,
10052 std::string* auth_token) OVERRIDE {
10053 *url_ = request->url;
10054 return HttpAuthHandlerMock::GenerateAuthTokenImpl(
10055 credentials, request, callback, auth_token);
10056 }
10057
10058 private:
10059 GURL* url_;
10060 };
10061
TEST_P(HttpNetworkTransactionTest,SpdyAlternateProtocolThroughProxy)10062 TEST_P(HttpNetworkTransactionTest, SpdyAlternateProtocolThroughProxy) {
10063 // This test ensures that the URL passed into the proxy is upgraded
10064 // to https when doing an Alternate Protocol upgrade.
10065 session_deps_.use_alternate_protocols = true;
10066 session_deps_.next_protos = SpdyNextProtos();
10067
10068 session_deps_.proxy_service.reset(
10069 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
10070 CapturingNetLog net_log;
10071 session_deps_.net_log = &net_log;
10072 GURL request_url;
10073 {
10074 HttpAuthHandlerMock::Factory* auth_factory =
10075 new HttpAuthHandlerMock::Factory();
10076 UrlRecordingHttpAuthHandlerMock* auth_handler =
10077 new UrlRecordingHttpAuthHandlerMock(&request_url);
10078 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_PROXY);
10079 auth_factory->set_do_init_from_challenge(true);
10080 session_deps_.http_auth_handler_factory.reset(auth_factory);
10081 }
10082
10083 HttpRequestInfo request;
10084 request.method = "GET";
10085 request.url = GURL("http://www.google.com");
10086 request.load_flags = 0;
10087
10088 // First round goes unauthenticated through the proxy.
10089 MockWrite data_writes_1[] = {
10090 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
10091 "Host: www.google.com\r\n"
10092 "Proxy-Connection: keep-alive\r\n"
10093 "\r\n"),
10094 };
10095 MockRead data_reads_1[] = {
10096 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
10097 MockRead("HTTP/1.1 200 OK\r\n"
10098 "Alternate-Protocol: 443:npn-spdy/2\r\n"
10099 "Proxy-Connection: close\r\n"
10100 "\r\n"),
10101 };
10102 StaticSocketDataProvider data_1(data_reads_1, arraysize(data_reads_1),
10103 data_writes_1, arraysize(data_writes_1));
10104
10105 // Second round tries to tunnel to www.google.com due to the
10106 // Alternate-Protocol announcement in the first round. It fails due
10107 // to a proxy authentication challenge.
10108 // After the failure, a tunnel is established to www.google.com using
10109 // Proxy-Authorization headers. There is then a SPDY request round.
10110 //
10111 // NOTE: Despite the "Proxy-Connection: Close", these are done on the
10112 // same MockTCPClientSocket since the underlying HttpNetworkClientSocket
10113 // does a Disconnect and Connect on the same socket, rather than trying
10114 // to obtain a new one.
10115 //
10116 // NOTE: Originally, the proxy response to the second CONNECT request
10117 // simply returned another 407 so the unit test could skip the SSL connection
10118 // establishment and SPDY framing issues. Alas, the
10119 // retry-http-when-alternate-protocol fails logic kicks in, which was more
10120 // complicated to set up expectations for than the SPDY session.
10121
10122 scoped_ptr<SpdyFrame> req(
10123 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
10124 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
10125 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
10126
10127 MockWrite data_writes_2[] = {
10128 // First connection attempt without Proxy-Authorization.
10129 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
10130 "Host: www.google.com\r\n"
10131 "Proxy-Connection: keep-alive\r\n"
10132 "\r\n"),
10133
10134 // Second connection attempt with Proxy-Authorization.
10135 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
10136 "Host: www.google.com\r\n"
10137 "Proxy-Connection: keep-alive\r\n"
10138 "Proxy-Authorization: auth_token\r\n"
10139 "\r\n"),
10140
10141 // SPDY request
10142 CreateMockWrite(*req),
10143 };
10144 const char kRejectConnectResponse[] = ("HTTP/1.1 407 Unauthorized\r\n"
10145 "Proxy-Authenticate: Mock\r\n"
10146 "Proxy-Connection: close\r\n"
10147 "\r\n");
10148 const char kAcceptConnectResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
10149 MockRead data_reads_2[] = {
10150 // First connection attempt fails
10151 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ, 1),
10152 MockRead(ASYNC, kRejectConnectResponse,
10153 arraysize(kRejectConnectResponse) - 1, 1),
10154
10155 // Second connection attempt passes
10156 MockRead(ASYNC, kAcceptConnectResponse,
10157 arraysize(kAcceptConnectResponse) -1, 4),
10158
10159 // SPDY response
10160 CreateMockRead(*resp.get(), 6),
10161 CreateMockRead(*data.get(), 6),
10162 MockRead(ASYNC, 0, 0, 6),
10163 };
10164 OrderedSocketData data_2(
10165 data_reads_2, arraysize(data_reads_2),
10166 data_writes_2, arraysize(data_writes_2));
10167
10168 SSLSocketDataProvider ssl(ASYNC, OK);
10169 ssl.SetNextProto(GetParam());
10170
10171 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
10172 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
10173 NULL, 0, NULL, 0);
10174 hanging_non_alternate_protocol_socket.set_connect_data(
10175 never_finishing_connect);
10176
10177 session_deps_.socket_factory->AddSocketDataProvider(&data_1);
10178 session_deps_.socket_factory->AddSocketDataProvider(&data_2);
10179 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10180 session_deps_.socket_factory->AddSocketDataProvider(
10181 &hanging_non_alternate_protocol_socket);
10182 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10183
10184 // First round should work and provide the Alternate-Protocol state.
10185 TestCompletionCallback callback_1;
10186 scoped_ptr<HttpTransaction> trans_1(
10187 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10188 int rv = trans_1->Start(&request, callback_1.callback(), BoundNetLog());
10189 EXPECT_EQ(ERR_IO_PENDING, rv);
10190 EXPECT_EQ(OK, callback_1.WaitForResult());
10191
10192 // Second round should attempt a tunnel connect and get an auth challenge.
10193 TestCompletionCallback callback_2;
10194 scoped_ptr<HttpTransaction> trans_2(
10195 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10196 rv = trans_2->Start(&request, callback_2.callback(), BoundNetLog());
10197 EXPECT_EQ(ERR_IO_PENDING, rv);
10198 EXPECT_EQ(OK, callback_2.WaitForResult());
10199 const HttpResponseInfo* response = trans_2->GetResponseInfo();
10200 ASSERT_TRUE(response != NULL);
10201 ASSERT_FALSE(response->auth_challenge.get() == NULL);
10202
10203 // Restart with auth. Tunnel should work and response received.
10204 TestCompletionCallback callback_3;
10205 rv = trans_2->RestartWithAuth(
10206 AuthCredentials(kFoo, kBar), callback_3.callback());
10207 EXPECT_EQ(ERR_IO_PENDING, rv);
10208 EXPECT_EQ(OK, callback_3.WaitForResult());
10209
10210 // After all that work, these two lines (or actually, just the scheme) are
10211 // what this test is all about. Make sure it happens correctly.
10212 EXPECT_EQ("https", request_url.scheme());
10213 EXPECT_EQ("www.google.com", request_url.host());
10214
10215 LoadTimingInfo load_timing_info;
10216 EXPECT_TRUE(trans_2->GetLoadTimingInfo(&load_timing_info));
10217 TestLoadTimingNotReusedWithPac(load_timing_info,
10218 CONNECT_TIMING_HAS_SSL_TIMES);
10219 }
10220
10221 // Test that if we cancel the transaction as the connection is completing, that
10222 // everything tears down correctly.
TEST_P(HttpNetworkTransactionTest,SimpleCancel)10223 TEST_P(HttpNetworkTransactionTest, SimpleCancel) {
10224 // Setup everything about the connection to complete synchronously, so that
10225 // after calling HttpNetworkTransaction::Start, the only thing we're waiting
10226 // for is the callback from the HttpStreamRequest.
10227 // Then cancel the transaction.
10228 // Verify that we don't crash.
10229 MockConnect mock_connect(SYNCHRONOUS, OK);
10230 MockRead data_reads[] = {
10231 MockRead(SYNCHRONOUS, "HTTP/1.0 200 OK\r\n\r\n"),
10232 MockRead(SYNCHRONOUS, "hello world"),
10233 MockRead(SYNCHRONOUS, OK),
10234 };
10235
10236 HttpRequestInfo request;
10237 request.method = "GET";
10238 request.url = GURL("http://www.google.com/");
10239 request.load_flags = 0;
10240
10241 session_deps_.host_resolver->set_synchronous_mode(true);
10242 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10243 scoped_ptr<HttpTransaction> trans(
10244 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
10245
10246 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
10247 data.set_connect_data(mock_connect);
10248 session_deps_.socket_factory->AddSocketDataProvider(&data);
10249
10250 TestCompletionCallback callback;
10251
10252 CapturingBoundNetLog log;
10253 int rv = trans->Start(&request, callback.callback(), log.bound());
10254 EXPECT_EQ(ERR_IO_PENDING, rv);
10255 trans.reset(); // Cancel the transaction here.
10256
10257 base::MessageLoop::current()->RunUntilIdle();
10258 }
10259
10260 // Test that if a transaction is cancelled after receiving the headers, the
10261 // stream is drained properly and added back to the socket pool. The main
10262 // purpose of this test is to make sure that an HttpStreamParser can be read
10263 // from after the HttpNetworkTransaction and the objects it owns have been
10264 // deleted.
10265 // See http://crbug.com/368418
TEST_P(HttpNetworkTransactionTest,CancelAfterHeaders)10266 TEST_P(HttpNetworkTransactionTest, CancelAfterHeaders) {
10267 MockRead data_reads[] = {
10268 MockRead(ASYNC, "HTTP/1.1 200 OK\r\n"),
10269 MockRead(ASYNC, "Content-Length: 2\r\n"),
10270 MockRead(ASYNC, "Connection: Keep-Alive\r\n\r\n"),
10271 MockRead(ASYNC, "1"),
10272 // 2 async reads are necessary to trigger a ReadResponseBody call after the
10273 // HttpNetworkTransaction has been deleted.
10274 MockRead(ASYNC, "2"),
10275 MockRead(SYNCHRONOUS, ERR_IO_PENDING), // Should never read this.
10276 };
10277 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
10278 session_deps_.socket_factory->AddSocketDataProvider(&data);
10279
10280 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10281
10282 {
10283 HttpRequestInfo request;
10284 request.method = "GET";
10285 request.url = GURL("http://www.google.com/");
10286 request.load_flags = 0;
10287
10288 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session);
10289 TestCompletionCallback callback;
10290
10291 int rv = trans.Start(&request, callback.callback(), BoundNetLog());
10292 EXPECT_EQ(ERR_IO_PENDING, rv);
10293 callback.WaitForResult();
10294
10295 const HttpResponseInfo* response = trans.GetResponseInfo();
10296 ASSERT_TRUE(response != NULL);
10297 EXPECT_TRUE(response->headers.get() != NULL);
10298 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10299
10300 // The transaction and HttpRequestInfo are deleted.
10301 }
10302
10303 // Let the HttpResponseBodyDrainer drain the socket.
10304 base::MessageLoop::current()->RunUntilIdle();
10305
10306 // Socket should now be idle, waiting to be reused.
10307 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session));
10308 }
10309
10310 // Test a basic GET request through a proxy.
TEST_P(HttpNetworkTransactionTest,ProxyGet)10311 TEST_P(HttpNetworkTransactionTest, ProxyGet) {
10312 session_deps_.proxy_service.reset(
10313 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
10314 CapturingBoundNetLog log;
10315 session_deps_.net_log = log.bound().net_log();
10316 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10317
10318 HttpRequestInfo request;
10319 request.method = "GET";
10320 request.url = GURL("http://www.google.com/");
10321
10322 MockWrite data_writes1[] = {
10323 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
10324 "Host: www.google.com\r\n"
10325 "Proxy-Connection: keep-alive\r\n\r\n"),
10326 };
10327
10328 MockRead data_reads1[] = {
10329 MockRead("HTTP/1.1 200 OK\r\n"),
10330 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10331 MockRead("Content-Length: 100\r\n\r\n"),
10332 MockRead(SYNCHRONOUS, OK),
10333 };
10334
10335 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
10336 data_writes1, arraysize(data_writes1));
10337 session_deps_.socket_factory->AddSocketDataProvider(&data1);
10338
10339 TestCompletionCallback callback1;
10340
10341 scoped_ptr<HttpTransaction> trans(
10342 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10343
10344 int rv = trans->Start(&request, callback1.callback(), log.bound());
10345 EXPECT_EQ(ERR_IO_PENDING, rv);
10346
10347 rv = callback1.WaitForResult();
10348 EXPECT_EQ(OK, rv);
10349
10350 const HttpResponseInfo* response = trans->GetResponseInfo();
10351 ASSERT_TRUE(response != NULL);
10352
10353 EXPECT_TRUE(response->headers->IsKeepAlive());
10354 EXPECT_EQ(200, response->headers->response_code());
10355 EXPECT_EQ(100, response->headers->GetContentLength());
10356 EXPECT_TRUE(response->was_fetched_via_proxy);
10357 EXPECT_TRUE(
10358 response->proxy_server.Equals(HostPortPair::FromString("myproxy:70")));
10359 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
10360
10361 LoadTimingInfo load_timing_info;
10362 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
10363 TestLoadTimingNotReusedWithPac(load_timing_info,
10364 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
10365 }
10366
10367 // Test a basic HTTPS GET request through a proxy.
TEST_P(HttpNetworkTransactionTest,ProxyTunnelGet)10368 TEST_P(HttpNetworkTransactionTest, ProxyTunnelGet) {
10369 session_deps_.proxy_service.reset(
10370 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
10371 CapturingBoundNetLog log;
10372 session_deps_.net_log = log.bound().net_log();
10373 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10374
10375 HttpRequestInfo request;
10376 request.method = "GET";
10377 request.url = GURL("https://www.google.com/");
10378
10379 // Since we have proxy, should try to establish tunnel.
10380 MockWrite data_writes1[] = {
10381 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
10382 "Host: www.google.com\r\n"
10383 "Proxy-Connection: keep-alive\r\n\r\n"),
10384
10385 MockWrite("GET / HTTP/1.1\r\n"
10386 "Host: www.google.com\r\n"
10387 "Connection: keep-alive\r\n\r\n"),
10388 };
10389
10390 MockRead data_reads1[] = {
10391 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
10392
10393 MockRead("HTTP/1.1 200 OK\r\n"),
10394 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10395 MockRead("Content-Length: 100\r\n\r\n"),
10396 MockRead(SYNCHRONOUS, OK),
10397 };
10398
10399 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
10400 data_writes1, arraysize(data_writes1));
10401 session_deps_.socket_factory->AddSocketDataProvider(&data1);
10402 SSLSocketDataProvider ssl(ASYNC, OK);
10403 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10404
10405 TestCompletionCallback callback1;
10406
10407 scoped_ptr<HttpTransaction> trans(
10408 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10409
10410 int rv = trans->Start(&request, callback1.callback(), log.bound());
10411 EXPECT_EQ(ERR_IO_PENDING, rv);
10412
10413 rv = callback1.WaitForResult();
10414 EXPECT_EQ(OK, rv);
10415 net::CapturingNetLog::CapturedEntryList entries;
10416 log.GetEntries(&entries);
10417 size_t pos = ExpectLogContainsSomewhere(
10418 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
10419 NetLog::PHASE_NONE);
10420 ExpectLogContainsSomewhere(
10421 entries, pos,
10422 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
10423 NetLog::PHASE_NONE);
10424
10425 const HttpResponseInfo* response = trans->GetResponseInfo();
10426 ASSERT_TRUE(response != NULL);
10427
10428 EXPECT_TRUE(response->headers->IsKeepAlive());
10429 EXPECT_EQ(200, response->headers->response_code());
10430 EXPECT_EQ(100, response->headers->GetContentLength());
10431 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
10432 EXPECT_TRUE(response->was_fetched_via_proxy);
10433 EXPECT_TRUE(
10434 response->proxy_server.Equals(HostPortPair::FromString("myproxy:70")));
10435
10436 LoadTimingInfo load_timing_info;
10437 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
10438 TestLoadTimingNotReusedWithPac(load_timing_info,
10439 CONNECT_TIMING_HAS_SSL_TIMES);
10440 }
10441
10442 // Test a basic HTTPS GET request through a proxy, but the server hangs up
10443 // while establishing the tunnel.
TEST_P(HttpNetworkTransactionTest,ProxyTunnelGetHangup)10444 TEST_P(HttpNetworkTransactionTest, ProxyTunnelGetHangup) {
10445 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
10446 CapturingBoundNetLog log;
10447 session_deps_.net_log = log.bound().net_log();
10448 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10449
10450 HttpRequestInfo request;
10451 request.method = "GET";
10452 request.url = GURL("https://www.google.com/");
10453
10454 // Since we have proxy, should try to establish tunnel.
10455 MockWrite data_writes1[] = {
10456 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
10457 "Host: www.google.com\r\n"
10458 "Proxy-Connection: keep-alive\r\n\r\n"),
10459
10460 MockWrite("GET / HTTP/1.1\r\n"
10461 "Host: www.google.com\r\n"
10462 "Connection: keep-alive\r\n\r\n"),
10463 };
10464
10465 MockRead data_reads1[] = {
10466 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
10467 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
10468 MockRead(ASYNC, 0, 0), // EOF
10469 };
10470
10471 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
10472 data_writes1, arraysize(data_writes1));
10473 session_deps_.socket_factory->AddSocketDataProvider(&data1);
10474 SSLSocketDataProvider ssl(ASYNC, OK);
10475 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10476
10477 TestCompletionCallback callback1;
10478
10479 scoped_ptr<HttpTransaction> trans(
10480 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10481
10482 int rv = trans->Start(&request, callback1.callback(), log.bound());
10483 EXPECT_EQ(ERR_IO_PENDING, rv);
10484
10485 rv = callback1.WaitForResult();
10486 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
10487 net::CapturingNetLog::CapturedEntryList entries;
10488 log.GetEntries(&entries);
10489 size_t pos = ExpectLogContainsSomewhere(
10490 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
10491 NetLog::PHASE_NONE);
10492 ExpectLogContainsSomewhere(
10493 entries, pos,
10494 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
10495 NetLog::PHASE_NONE);
10496 }
10497
10498 // Test for crbug.com/55424.
TEST_P(HttpNetworkTransactionTest,PreconnectWithExistingSpdySession)10499 TEST_P(HttpNetworkTransactionTest, PreconnectWithExistingSpdySession) {
10500 scoped_ptr<SpdyFrame> req(
10501 spdy_util_.ConstructSpdyGet("https://www.google.com", false, 1, LOWEST));
10502 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
10503
10504 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
10505 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
10506 MockRead spdy_reads[] = {
10507 CreateMockRead(*resp),
10508 CreateMockRead(*data),
10509 MockRead(ASYNC, 0, 0),
10510 };
10511
10512 DelayedSocketData spdy_data(
10513 1, // wait for one write to finish before reading.
10514 spdy_reads, arraysize(spdy_reads),
10515 spdy_writes, arraysize(spdy_writes));
10516 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
10517
10518 SSLSocketDataProvider ssl(ASYNC, OK);
10519 ssl.SetNextProto(GetParam());
10520 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10521
10522 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10523
10524 // Set up an initial SpdySession in the pool to reuse.
10525 HostPortPair host_port_pair("www.google.com", 443);
10526 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
10527 PRIVACY_MODE_DISABLED);
10528 base::WeakPtr<SpdySession> spdy_session =
10529 CreateInsecureSpdySession(session, key, BoundNetLog());
10530
10531 HttpRequestInfo request;
10532 request.method = "GET";
10533 request.url = GURL("https://www.google.com/");
10534 request.load_flags = 0;
10535
10536 // This is the important line that marks this as a preconnect.
10537 request.motivation = HttpRequestInfo::PRECONNECT_MOTIVATED;
10538
10539 scoped_ptr<HttpTransaction> trans(
10540 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10541
10542 TestCompletionCallback callback;
10543 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
10544 EXPECT_EQ(ERR_IO_PENDING, rv);
10545 EXPECT_EQ(OK, callback.WaitForResult());
10546 }
10547
10548 // Given a net error, cause that error to be returned from the first Write()
10549 // call and verify that the HttpTransaction fails with that error.
CheckErrorIsPassedBack(int error,IoMode mode)10550 void HttpNetworkTransactionTest::CheckErrorIsPassedBack(
10551 int error, IoMode mode) {
10552 net::HttpRequestInfo request_info;
10553 request_info.url = GURL("https://www.example.com/");
10554 request_info.method = "GET";
10555 request_info.load_flags = net::LOAD_NORMAL;
10556
10557 SSLSocketDataProvider ssl_data(mode, OK);
10558 net::MockWrite data_writes[] = {
10559 net::MockWrite(mode, error),
10560 };
10561 net::StaticSocketDataProvider data(NULL, 0,
10562 data_writes, arraysize(data_writes));
10563 session_deps_.socket_factory->AddSocketDataProvider(&data);
10564 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data);
10565
10566 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10567 scoped_ptr<HttpTransaction> trans(
10568 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10569
10570 TestCompletionCallback callback;
10571 int rv = trans->Start(&request_info, callback.callback(), net::BoundNetLog());
10572 if (rv == net::ERR_IO_PENDING)
10573 rv = callback.WaitForResult();
10574 ASSERT_EQ(error, rv);
10575 }
10576
TEST_P(HttpNetworkTransactionTest,SSLWriteCertError)10577 TEST_P(HttpNetworkTransactionTest, SSLWriteCertError) {
10578 // Just check a grab bag of cert errors.
10579 static const int kErrors[] = {
10580 ERR_CERT_COMMON_NAME_INVALID,
10581 ERR_CERT_AUTHORITY_INVALID,
10582 ERR_CERT_DATE_INVALID,
10583 };
10584 for (size_t i = 0; i < arraysize(kErrors); i++) {
10585 CheckErrorIsPassedBack(kErrors[i], ASYNC);
10586 CheckErrorIsPassedBack(kErrors[i], SYNCHRONOUS);
10587 }
10588 }
10589
10590 // Ensure that a client certificate is removed from the SSL client auth
10591 // cache when:
10592 // 1) No proxy is involved.
10593 // 2) TLS False Start is disabled.
10594 // 3) The initial TLS handshake requests a client certificate.
10595 // 4) The client supplies an invalid/unacceptable certificate.
TEST_P(HttpNetworkTransactionTest,ClientAuthCertCache_Direct_NoFalseStart)10596 TEST_P(HttpNetworkTransactionTest,
10597 ClientAuthCertCache_Direct_NoFalseStart) {
10598 net::HttpRequestInfo request_info;
10599 request_info.url = GURL("https://www.example.com/");
10600 request_info.method = "GET";
10601 request_info.load_flags = net::LOAD_NORMAL;
10602
10603 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
10604 cert_request->host_and_port = HostPortPair("www.example.com", 443);
10605
10606 // [ssl_]data1 contains the data for the first SSL handshake. When a
10607 // CertificateRequest is received for the first time, the handshake will
10608 // be aborted to allow the caller to provide a certificate.
10609 SSLSocketDataProvider ssl_data1(ASYNC, net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
10610 ssl_data1.cert_request_info = cert_request.get();
10611 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
10612 net::StaticSocketDataProvider data1(NULL, 0, NULL, 0);
10613 session_deps_.socket_factory->AddSocketDataProvider(&data1);
10614
10615 // [ssl_]data2 contains the data for the second SSL handshake. When TLS
10616 // False Start is not being used, the result of the SSL handshake will be
10617 // returned as part of the SSLClientSocket::Connect() call. This test
10618 // matches the result of a server sending a handshake_failure alert,
10619 // rather than a Finished message, because it requires a client
10620 // certificate and none was supplied.
10621 SSLSocketDataProvider ssl_data2(ASYNC, net::ERR_SSL_PROTOCOL_ERROR);
10622 ssl_data2.cert_request_info = cert_request.get();
10623 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
10624 net::StaticSocketDataProvider data2(NULL, 0, NULL, 0);
10625 session_deps_.socket_factory->AddSocketDataProvider(&data2);
10626
10627 // [ssl_]data3 contains the data for the third SSL handshake. When a
10628 // connection to a server fails during an SSL handshake,
10629 // HttpNetworkTransaction will attempt to fallback to TLSv1 if the previous
10630 // connection was attempted with TLSv1.1. This is transparent to the caller
10631 // of the HttpNetworkTransaction. Because this test failure is due to
10632 // requiring a client certificate, this fallback handshake should also
10633 // fail.
10634 SSLSocketDataProvider ssl_data3(ASYNC, net::ERR_SSL_PROTOCOL_ERROR);
10635 ssl_data3.cert_request_info = cert_request.get();
10636 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
10637 net::StaticSocketDataProvider data3(NULL, 0, NULL, 0);
10638 session_deps_.socket_factory->AddSocketDataProvider(&data3);
10639
10640 // [ssl_]data4 contains the data for the fourth SSL handshake. When a
10641 // connection to a server fails during an SSL handshake,
10642 // HttpNetworkTransaction will attempt to fallback to SSLv3 if the previous
10643 // connection was attempted with TLSv1. This is transparent to the caller
10644 // of the HttpNetworkTransaction. Because this test failure is due to
10645 // requiring a client certificate, this fallback handshake should also
10646 // fail.
10647 SSLSocketDataProvider ssl_data4(ASYNC, net::ERR_SSL_PROTOCOL_ERROR);
10648 ssl_data4.cert_request_info = cert_request.get();
10649 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data4);
10650 net::StaticSocketDataProvider data4(NULL, 0, NULL, 0);
10651 session_deps_.socket_factory->AddSocketDataProvider(&data4);
10652
10653 // Need one more if TLSv1.2 is enabled.
10654 SSLSocketDataProvider ssl_data5(ASYNC, net::ERR_SSL_PROTOCOL_ERROR);
10655 ssl_data5.cert_request_info = cert_request.get();
10656 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data5);
10657 net::StaticSocketDataProvider data5(NULL, 0, NULL, 0);
10658 session_deps_.socket_factory->AddSocketDataProvider(&data5);
10659
10660 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10661 scoped_ptr<HttpTransaction> trans(
10662 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10663
10664 // Begin the SSL handshake with the peer. This consumes ssl_data1.
10665 TestCompletionCallback callback;
10666 int rv = trans->Start(&request_info, callback.callback(), net::BoundNetLog());
10667 ASSERT_EQ(net::ERR_IO_PENDING, rv);
10668
10669 // Complete the SSL handshake, which should abort due to requiring a
10670 // client certificate.
10671 rv = callback.WaitForResult();
10672 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
10673
10674 // Indicate that no certificate should be supplied. From the perspective
10675 // of SSLClientCertCache, NULL is just as meaningful as a real
10676 // certificate, so this is the same as supply a
10677 // legitimate-but-unacceptable certificate.
10678 rv = trans->RestartWithCertificate(NULL, callback.callback());
10679 ASSERT_EQ(net::ERR_IO_PENDING, rv);
10680
10681 // Ensure the certificate was added to the client auth cache before
10682 // allowing the connection to continue restarting.
10683 scoped_refptr<X509Certificate> client_cert;
10684 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup(
10685 HostPortPair("www.example.com", 443), &client_cert));
10686 ASSERT_EQ(NULL, client_cert.get());
10687
10688 // Restart the handshake. This will consume ssl_data2, which fails, and
10689 // then consume ssl_data3 and ssl_data4, both of which should also fail.
10690 // The result code is checked against what ssl_data4 should return.
10691 rv = callback.WaitForResult();
10692 ASSERT_EQ(net::ERR_SSL_PROTOCOL_ERROR, rv);
10693
10694 // Ensure that the client certificate is removed from the cache on a
10695 // handshake failure.
10696 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
10697 HostPortPair("www.example.com", 443), &client_cert));
10698 }
10699
10700 // Ensure that a client certificate is removed from the SSL client auth
10701 // cache when:
10702 // 1) No proxy is involved.
10703 // 2) TLS False Start is enabled.
10704 // 3) The initial TLS handshake requests a client certificate.
10705 // 4) The client supplies an invalid/unacceptable certificate.
TEST_P(HttpNetworkTransactionTest,ClientAuthCertCache_Direct_FalseStart)10706 TEST_P(HttpNetworkTransactionTest,
10707 ClientAuthCertCache_Direct_FalseStart) {
10708 net::HttpRequestInfo request_info;
10709 request_info.url = GURL("https://www.example.com/");
10710 request_info.method = "GET";
10711 request_info.load_flags = net::LOAD_NORMAL;
10712
10713 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
10714 cert_request->host_and_port = HostPortPair("www.example.com", 443);
10715
10716 // When TLS False Start is used, SSLClientSocket::Connect() calls will
10717 // return successfully after reading up to the peer's Certificate message.
10718 // This is to allow the caller to call SSLClientSocket::Write(), which can
10719 // enqueue application data to be sent in the same packet as the
10720 // ChangeCipherSpec and Finished messages.
10721 // The actual handshake will be finished when SSLClientSocket::Read() is
10722 // called, which expects to process the peer's ChangeCipherSpec and
10723 // Finished messages. If there was an error negotiating with the peer,
10724 // such as due to the peer requiring a client certificate when none was
10725 // supplied, the alert sent by the peer won't be processed until Read() is
10726 // called.
10727
10728 // Like the non-False Start case, when a client certificate is requested by
10729 // the peer, the handshake is aborted during the Connect() call.
10730 // [ssl_]data1 represents the initial SSL handshake with the peer.
10731 SSLSocketDataProvider ssl_data1(ASYNC, net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
10732 ssl_data1.cert_request_info = cert_request.get();
10733 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
10734 net::StaticSocketDataProvider data1(NULL, 0, NULL, 0);
10735 session_deps_.socket_factory->AddSocketDataProvider(&data1);
10736
10737 // When a client certificate is supplied, Connect() will not be aborted
10738 // when the peer requests the certificate. Instead, the handshake will
10739 // artificially succeed, allowing the caller to write the HTTP request to
10740 // the socket. The handshake messages are not processed until Read() is
10741 // called, which then detects that the handshake was aborted, due to the
10742 // peer sending a handshake_failure because it requires a client
10743 // certificate.
10744 SSLSocketDataProvider ssl_data2(ASYNC, net::OK);
10745 ssl_data2.cert_request_info = cert_request.get();
10746 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
10747 net::MockRead data2_reads[] = {
10748 net::MockRead(ASYNC /* async */, net::ERR_SSL_PROTOCOL_ERROR),
10749 };
10750 net::StaticSocketDataProvider data2(
10751 data2_reads, arraysize(data2_reads), NULL, 0);
10752 session_deps_.socket_factory->AddSocketDataProvider(&data2);
10753
10754 // As described in ClientAuthCertCache_Direct_NoFalseStart, [ssl_]data3 is
10755 // the data for the SSL handshake once the TLSv1.1 connection falls back to
10756 // TLSv1. It has the same behaviour as [ssl_]data2.
10757 SSLSocketDataProvider ssl_data3(ASYNC, net::OK);
10758 ssl_data3.cert_request_info = cert_request.get();
10759 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
10760 net::StaticSocketDataProvider data3(
10761 data2_reads, arraysize(data2_reads), NULL, 0);
10762 session_deps_.socket_factory->AddSocketDataProvider(&data3);
10763
10764 // [ssl_]data4 is the data for the SSL handshake once the TLSv1 connection
10765 // falls back to SSLv3. It has the same behaviour as [ssl_]data2.
10766 SSLSocketDataProvider ssl_data4(ASYNC, net::OK);
10767 ssl_data4.cert_request_info = cert_request.get();
10768 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data4);
10769 net::StaticSocketDataProvider data4(
10770 data2_reads, arraysize(data2_reads), NULL, 0);
10771 session_deps_.socket_factory->AddSocketDataProvider(&data4);
10772
10773 // Need one more if TLSv1.2 is enabled.
10774 SSLSocketDataProvider ssl_data5(ASYNC, net::OK);
10775 ssl_data5.cert_request_info = cert_request.get();
10776 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data5);
10777 net::StaticSocketDataProvider data5(
10778 data2_reads, arraysize(data2_reads), NULL, 0);
10779 session_deps_.socket_factory->AddSocketDataProvider(&data5);
10780
10781 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10782 scoped_ptr<HttpTransaction> trans(
10783 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10784
10785 // Begin the initial SSL handshake.
10786 TestCompletionCallback callback;
10787 int rv = trans->Start(&request_info, callback.callback(), net::BoundNetLog());
10788 ASSERT_EQ(net::ERR_IO_PENDING, rv);
10789
10790 // Complete the SSL handshake, which should abort due to requiring a
10791 // client certificate.
10792 rv = callback.WaitForResult();
10793 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
10794
10795 // Indicate that no certificate should be supplied. From the perspective
10796 // of SSLClientCertCache, NULL is just as meaningful as a real
10797 // certificate, so this is the same as supply a
10798 // legitimate-but-unacceptable certificate.
10799 rv = trans->RestartWithCertificate(NULL, callback.callback());
10800 ASSERT_EQ(net::ERR_IO_PENDING, rv);
10801
10802 // Ensure the certificate was added to the client auth cache before
10803 // allowing the connection to continue restarting.
10804 scoped_refptr<X509Certificate> client_cert;
10805 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup(
10806 HostPortPair("www.example.com", 443), &client_cert));
10807 ASSERT_EQ(NULL, client_cert.get());
10808
10809 // Restart the handshake. This will consume ssl_data2, which fails, and
10810 // then consume ssl_data3 and ssl_data4, both of which should also fail.
10811 // The result code is checked against what ssl_data4 should return.
10812 rv = callback.WaitForResult();
10813 ASSERT_EQ(net::ERR_SSL_PROTOCOL_ERROR, rv);
10814
10815 // Ensure that the client certificate is removed from the cache on a
10816 // handshake failure.
10817 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
10818 HostPortPair("www.example.com", 443), &client_cert));
10819 }
10820
10821 // Ensure that a client certificate is removed from the SSL client auth
10822 // cache when:
10823 // 1) An HTTPS proxy is involved.
10824 // 3) The HTTPS proxy requests a client certificate.
10825 // 4) The client supplies an invalid/unacceptable certificate for the
10826 // proxy.
10827 // The test is repeated twice, first for connecting to an HTTPS endpoint,
10828 // then for connecting to an HTTP endpoint.
TEST_P(HttpNetworkTransactionTest,ClientAuthCertCache_Proxy_Fail)10829 TEST_P(HttpNetworkTransactionTest, ClientAuthCertCache_Proxy_Fail) {
10830 session_deps_.proxy_service.reset(
10831 ProxyService::CreateFixed("https://proxy:70"));
10832 CapturingBoundNetLog log;
10833 session_deps_.net_log = log.bound().net_log();
10834
10835 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
10836 cert_request->host_and_port = HostPortPair("proxy", 70);
10837
10838 // See ClientAuthCertCache_Direct_NoFalseStart for the explanation of
10839 // [ssl_]data[1-3]. Rather than represending the endpoint
10840 // (www.example.com:443), they represent failures with the HTTPS proxy
10841 // (proxy:70).
10842 SSLSocketDataProvider ssl_data1(ASYNC, net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
10843 ssl_data1.cert_request_info = cert_request.get();
10844 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
10845 net::StaticSocketDataProvider data1(NULL, 0, NULL, 0);
10846 session_deps_.socket_factory->AddSocketDataProvider(&data1);
10847
10848 SSLSocketDataProvider ssl_data2(ASYNC, net::ERR_SSL_PROTOCOL_ERROR);
10849 ssl_data2.cert_request_info = cert_request.get();
10850 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
10851 net::StaticSocketDataProvider data2(NULL, 0, NULL, 0);
10852 session_deps_.socket_factory->AddSocketDataProvider(&data2);
10853
10854 // TODO(wtc): find out why this unit test doesn't need [ssl_]data3.
10855 #if 0
10856 SSLSocketDataProvider ssl_data3(ASYNC, net::ERR_SSL_PROTOCOL_ERROR);
10857 ssl_data3.cert_request_info = cert_request.get();
10858 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
10859 net::StaticSocketDataProvider data3(NULL, 0, NULL, 0);
10860 session_deps_.socket_factory->AddSocketDataProvider(&data3);
10861 #endif
10862
10863 net::HttpRequestInfo requests[2];
10864 requests[0].url = GURL("https://www.example.com/");
10865 requests[0].method = "GET";
10866 requests[0].load_flags = net::LOAD_NORMAL;
10867
10868 requests[1].url = GURL("http://www.example.com/");
10869 requests[1].method = "GET";
10870 requests[1].load_flags = net::LOAD_NORMAL;
10871
10872 for (size_t i = 0; i < arraysize(requests); ++i) {
10873 session_deps_.socket_factory->ResetNextMockIndexes();
10874 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10875 scoped_ptr<HttpNetworkTransaction> trans(
10876 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10877
10878 // Begin the SSL handshake with the proxy.
10879 TestCompletionCallback callback;
10880 int rv = trans->Start(
10881 &requests[i], callback.callback(), net::BoundNetLog());
10882 ASSERT_EQ(net::ERR_IO_PENDING, rv);
10883
10884 // Complete the SSL handshake, which should abort due to requiring a
10885 // client certificate.
10886 rv = callback.WaitForResult();
10887 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
10888
10889 // Indicate that no certificate should be supplied. From the perspective
10890 // of SSLClientCertCache, NULL is just as meaningful as a real
10891 // certificate, so this is the same as supply a
10892 // legitimate-but-unacceptable certificate.
10893 rv = trans->RestartWithCertificate(NULL, callback.callback());
10894 ASSERT_EQ(net::ERR_IO_PENDING, rv);
10895
10896 // Ensure the certificate was added to the client auth cache before
10897 // allowing the connection to continue restarting.
10898 scoped_refptr<X509Certificate> client_cert;
10899 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup(
10900 HostPortPair("proxy", 70), &client_cert));
10901 ASSERT_EQ(NULL, client_cert.get());
10902 // Ensure the certificate was NOT cached for the endpoint. This only
10903 // applies to HTTPS requests, but is fine to check for HTTP requests.
10904 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
10905 HostPortPair("www.example.com", 443), &client_cert));
10906
10907 // Restart the handshake. This will consume ssl_data2, which fails, and
10908 // then consume ssl_data3, which should also fail. The result code is
10909 // checked against what ssl_data3 should return.
10910 rv = callback.WaitForResult();
10911 ASSERT_EQ(net::ERR_PROXY_CONNECTION_FAILED, rv);
10912
10913 // Now that the new handshake has failed, ensure that the client
10914 // certificate was removed from the client auth cache.
10915 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
10916 HostPortPair("proxy", 70), &client_cert));
10917 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
10918 HostPortPair("www.example.com", 443), &client_cert));
10919 }
10920 }
10921
10922 // Unlike TEST/TEST_F, which are macros that expand to further macros,
10923 // TEST_P is a macro that expands directly to code that stringizes the
10924 // arguments. As a result, macros passed as parameters (such as prefix
10925 // or test_case_name) will not be expanded by the preprocessor. To
10926 // work around this, indirect the macro for TEST_P, so that the
10927 // pre-processor will expand macros such as MAYBE_test_name before
10928 // instantiating the test.
10929 #define WRAPPED_TEST_P(test_case_name, test_name) \
10930 TEST_P(test_case_name, test_name)
10931
10932 // Times out on Win7 dbg(2) bot. http://crbug.com/124776
10933 #if defined(OS_WIN)
10934 #define MAYBE_UseIPConnectionPooling DISABLED_UseIPConnectionPooling
10935 #else
10936 #define MAYBE_UseIPConnectionPooling UseIPConnectionPooling
10937 #endif
WRAPPED_TEST_P(HttpNetworkTransactionTest,MAYBE_UseIPConnectionPooling)10938 WRAPPED_TEST_P(HttpNetworkTransactionTest, MAYBE_UseIPConnectionPooling) {
10939 session_deps_.use_alternate_protocols = true;
10940 session_deps_.next_protos = SpdyNextProtos();
10941
10942 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
10943 session_deps_.host_resolver.reset(new MockCachingHostResolver());
10944 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10945 SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
10946 pool_peer.DisableDomainAuthenticationVerification();
10947
10948 SSLSocketDataProvider ssl(ASYNC, OK);
10949 ssl.SetNextProto(GetParam());
10950 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10951
10952 scoped_ptr<SpdyFrame> host1_req(
10953 spdy_util_.ConstructSpdyGet("https://www.google.com", false, 1, LOWEST));
10954 scoped_ptr<SpdyFrame> host2_req(
10955 spdy_util_.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST));
10956 MockWrite spdy_writes[] = {
10957 CreateMockWrite(*host1_req, 1),
10958 CreateMockWrite(*host2_req, 4),
10959 };
10960 scoped_ptr<SpdyFrame> host1_resp(
10961 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
10962 scoped_ptr<SpdyFrame> host1_resp_body(
10963 spdy_util_.ConstructSpdyBodyFrame(1, true));
10964 scoped_ptr<SpdyFrame> host2_resp(
10965 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
10966 scoped_ptr<SpdyFrame> host2_resp_body(
10967 spdy_util_.ConstructSpdyBodyFrame(3, true));
10968 MockRead spdy_reads[] = {
10969 CreateMockRead(*host1_resp, 2),
10970 CreateMockRead(*host1_resp_body, 3),
10971 CreateMockRead(*host2_resp, 5),
10972 CreateMockRead(*host2_resp_body, 6),
10973 MockRead(ASYNC, 0, 7),
10974 };
10975
10976 IPAddressNumber ip;
10977 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip));
10978 IPEndPoint peer_addr = IPEndPoint(ip, 443);
10979 MockConnect connect(ASYNC, OK, peer_addr);
10980 OrderedSocketData spdy_data(
10981 connect,
10982 spdy_reads, arraysize(spdy_reads),
10983 spdy_writes, arraysize(spdy_writes));
10984 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
10985
10986 TestCompletionCallback callback;
10987 HttpRequestInfo request1;
10988 request1.method = "GET";
10989 request1.url = GURL("https://www.google.com/");
10990 request1.load_flags = 0;
10991 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
10992
10993 int rv = trans1.Start(&request1, callback.callback(), BoundNetLog());
10994 EXPECT_EQ(ERR_IO_PENDING, rv);
10995 EXPECT_EQ(OK, callback.WaitForResult());
10996
10997 const HttpResponseInfo* response = trans1.GetResponseInfo();
10998 ASSERT_TRUE(response != NULL);
10999 ASSERT_TRUE(response->headers.get() != NULL);
11000 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11001
11002 std::string response_data;
11003 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
11004 EXPECT_EQ("hello!", response_data);
11005
11006 // Preload www.gmail.com into HostCache.
11007 HostPortPair host_port("www.gmail.com", 443);
11008 HostResolver::RequestInfo resolve_info(host_port);
11009 AddressList ignored;
11010 rv = session_deps_.host_resolver->Resolve(resolve_info,
11011 DEFAULT_PRIORITY,
11012 &ignored,
11013 callback.callback(),
11014 NULL,
11015 BoundNetLog());
11016 EXPECT_EQ(ERR_IO_PENDING, rv);
11017 rv = callback.WaitForResult();
11018 EXPECT_EQ(OK, rv);
11019
11020 HttpRequestInfo request2;
11021 request2.method = "GET";
11022 request2.url = GURL("https://www.gmail.com/");
11023 request2.load_flags = 0;
11024 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
11025
11026 rv = trans2.Start(&request2, callback.callback(), BoundNetLog());
11027 EXPECT_EQ(ERR_IO_PENDING, rv);
11028 EXPECT_EQ(OK, callback.WaitForResult());
11029
11030 response = trans2.GetResponseInfo();
11031 ASSERT_TRUE(response != NULL);
11032 ASSERT_TRUE(response->headers.get() != NULL);
11033 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11034 EXPECT_TRUE(response->was_fetched_via_spdy);
11035 EXPECT_TRUE(response->was_npn_negotiated);
11036 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
11037 EXPECT_EQ("hello!", response_data);
11038 }
11039 #undef MAYBE_UseIPConnectionPooling
11040
TEST_P(HttpNetworkTransactionTest,UseIPConnectionPoolingAfterResolution)11041 TEST_P(HttpNetworkTransactionTest, UseIPConnectionPoolingAfterResolution) {
11042 session_deps_.use_alternate_protocols = true;
11043 session_deps_.next_protos = SpdyNextProtos();
11044
11045 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
11046 session_deps_.host_resolver.reset(new MockCachingHostResolver());
11047 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11048 SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
11049 pool_peer.DisableDomainAuthenticationVerification();
11050
11051 SSLSocketDataProvider ssl(ASYNC, OK);
11052 ssl.SetNextProto(GetParam());
11053 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11054
11055 scoped_ptr<SpdyFrame> host1_req(
11056 spdy_util_.ConstructSpdyGet("https://www.google.com", false, 1, LOWEST));
11057 scoped_ptr<SpdyFrame> host2_req(
11058 spdy_util_.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST));
11059 MockWrite spdy_writes[] = {
11060 CreateMockWrite(*host1_req, 1),
11061 CreateMockWrite(*host2_req, 4),
11062 };
11063 scoped_ptr<SpdyFrame> host1_resp(
11064 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11065 scoped_ptr<SpdyFrame> host1_resp_body(
11066 spdy_util_.ConstructSpdyBodyFrame(1, true));
11067 scoped_ptr<SpdyFrame> host2_resp(
11068 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
11069 scoped_ptr<SpdyFrame> host2_resp_body(
11070 spdy_util_.ConstructSpdyBodyFrame(3, true));
11071 MockRead spdy_reads[] = {
11072 CreateMockRead(*host1_resp, 2),
11073 CreateMockRead(*host1_resp_body, 3),
11074 CreateMockRead(*host2_resp, 5),
11075 CreateMockRead(*host2_resp_body, 6),
11076 MockRead(ASYNC, 0, 7),
11077 };
11078
11079 IPAddressNumber ip;
11080 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip));
11081 IPEndPoint peer_addr = IPEndPoint(ip, 443);
11082 MockConnect connect(ASYNC, OK, peer_addr);
11083 OrderedSocketData spdy_data(
11084 connect,
11085 spdy_reads, arraysize(spdy_reads),
11086 spdy_writes, arraysize(spdy_writes));
11087 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
11088
11089 TestCompletionCallback callback;
11090 HttpRequestInfo request1;
11091 request1.method = "GET";
11092 request1.url = GURL("https://www.google.com/");
11093 request1.load_flags = 0;
11094 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
11095
11096 int rv = trans1.Start(&request1, callback.callback(), BoundNetLog());
11097 EXPECT_EQ(ERR_IO_PENDING, rv);
11098 EXPECT_EQ(OK, callback.WaitForResult());
11099
11100 const HttpResponseInfo* response = trans1.GetResponseInfo();
11101 ASSERT_TRUE(response != NULL);
11102 ASSERT_TRUE(response->headers.get() != NULL);
11103 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11104
11105 std::string response_data;
11106 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
11107 EXPECT_EQ("hello!", response_data);
11108
11109 HttpRequestInfo request2;
11110 request2.method = "GET";
11111 request2.url = GURL("https://www.gmail.com/");
11112 request2.load_flags = 0;
11113 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
11114
11115 rv = trans2.Start(&request2, callback.callback(), BoundNetLog());
11116 EXPECT_EQ(ERR_IO_PENDING, rv);
11117 EXPECT_EQ(OK, callback.WaitForResult());
11118
11119 response = trans2.GetResponseInfo();
11120 ASSERT_TRUE(response != NULL);
11121 ASSERT_TRUE(response->headers.get() != NULL);
11122 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11123 EXPECT_TRUE(response->was_fetched_via_spdy);
11124 EXPECT_TRUE(response->was_npn_negotiated);
11125 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
11126 EXPECT_EQ("hello!", response_data);
11127 }
11128
11129 class OneTimeCachingHostResolver : public net::HostResolver {
11130 public:
OneTimeCachingHostResolver(const HostPortPair & host_port)11131 explicit OneTimeCachingHostResolver(const HostPortPair& host_port)
11132 : host_port_(host_port) {}
~OneTimeCachingHostResolver()11133 virtual ~OneTimeCachingHostResolver() {}
11134
rules()11135 RuleBasedHostResolverProc* rules() { return host_resolver_.rules(); }
11136
11137 // HostResolver methods:
Resolve(const RequestInfo & info,RequestPriority priority,AddressList * addresses,const CompletionCallback & callback,RequestHandle * out_req,const BoundNetLog & net_log)11138 virtual int Resolve(const RequestInfo& info,
11139 RequestPriority priority,
11140 AddressList* addresses,
11141 const CompletionCallback& callback,
11142 RequestHandle* out_req,
11143 const BoundNetLog& net_log) OVERRIDE {
11144 return host_resolver_.Resolve(
11145 info, priority, addresses, callback, out_req, net_log);
11146 }
11147
ResolveFromCache(const RequestInfo & info,AddressList * addresses,const BoundNetLog & net_log)11148 virtual int ResolveFromCache(const RequestInfo& info,
11149 AddressList* addresses,
11150 const BoundNetLog& net_log) OVERRIDE {
11151 int rv = host_resolver_.ResolveFromCache(info, addresses, net_log);
11152 if (rv == OK && info.host_port_pair().Equals(host_port_))
11153 host_resolver_.GetHostCache()->clear();
11154 return rv;
11155 }
11156
CancelRequest(RequestHandle req)11157 virtual void CancelRequest(RequestHandle req) OVERRIDE {
11158 host_resolver_.CancelRequest(req);
11159 }
11160
GetMockHostResolver()11161 MockCachingHostResolver* GetMockHostResolver() {
11162 return &host_resolver_;
11163 }
11164
11165 private:
11166 MockCachingHostResolver host_resolver_;
11167 const HostPortPair host_port_;
11168 };
11169
11170 // Times out on Win7 dbg(2) bot. http://crbug.com/124776
11171 #if defined(OS_WIN)
11172 #define MAYBE_UseIPConnectionPoolingWithHostCacheExpiration \
11173 DISABLED_UseIPConnectionPoolingWithHostCacheExpiration
11174 #else
11175 #define MAYBE_UseIPConnectionPoolingWithHostCacheExpiration \
11176 UseIPConnectionPoolingWithHostCacheExpiration
11177 #endif
WRAPPED_TEST_P(HttpNetworkTransactionTest,MAYBE_UseIPConnectionPoolingWithHostCacheExpiration)11178 WRAPPED_TEST_P(HttpNetworkTransactionTest,
11179 MAYBE_UseIPConnectionPoolingWithHostCacheExpiration) {
11180 // Times out on Win7 dbg(2) bot. http://crbug.com/124776 . (MAYBE_
11181 // prefix doesn't work with parametrized tests).
11182 #if defined(OS_WIN)
11183 return;
11184 #else
11185 session_deps_.use_alternate_protocols = true;
11186 session_deps_.next_protos = SpdyNextProtos();
11187
11188 // Set up a special HttpNetworkSession with a OneTimeCachingHostResolver.
11189 OneTimeCachingHostResolver host_resolver(HostPortPair("www.gmail.com", 443));
11190 HttpNetworkSession::Params params =
11191 SpdySessionDependencies::CreateSessionParams(&session_deps_);
11192 params.host_resolver = &host_resolver;
11193 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11194 SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
11195 pool_peer.DisableDomainAuthenticationVerification();
11196
11197 SSLSocketDataProvider ssl(ASYNC, OK);
11198 ssl.SetNextProto(GetParam());
11199 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11200
11201 scoped_ptr<SpdyFrame> host1_req(
11202 spdy_util_.ConstructSpdyGet("https://www.google.com", false, 1, LOWEST));
11203 scoped_ptr<SpdyFrame> host2_req(
11204 spdy_util_.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST));
11205 MockWrite spdy_writes[] = {
11206 CreateMockWrite(*host1_req, 1),
11207 CreateMockWrite(*host2_req, 4),
11208 };
11209 scoped_ptr<SpdyFrame> host1_resp(
11210 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11211 scoped_ptr<SpdyFrame> host1_resp_body(
11212 spdy_util_.ConstructSpdyBodyFrame(1, true));
11213 scoped_ptr<SpdyFrame> host2_resp(
11214 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
11215 scoped_ptr<SpdyFrame> host2_resp_body(
11216 spdy_util_.ConstructSpdyBodyFrame(3, true));
11217 MockRead spdy_reads[] = {
11218 CreateMockRead(*host1_resp, 2),
11219 CreateMockRead(*host1_resp_body, 3),
11220 CreateMockRead(*host2_resp, 5),
11221 CreateMockRead(*host2_resp_body, 6),
11222 MockRead(ASYNC, 0, 7),
11223 };
11224
11225 IPAddressNumber ip;
11226 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip));
11227 IPEndPoint peer_addr = IPEndPoint(ip, 443);
11228 MockConnect connect(ASYNC, OK, peer_addr);
11229 OrderedSocketData spdy_data(
11230 connect,
11231 spdy_reads, arraysize(spdy_reads),
11232 spdy_writes, arraysize(spdy_writes));
11233 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
11234
11235 TestCompletionCallback callback;
11236 HttpRequestInfo request1;
11237 request1.method = "GET";
11238 request1.url = GURL("https://www.google.com/");
11239 request1.load_flags = 0;
11240 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
11241
11242 int rv = trans1.Start(&request1, callback.callback(), BoundNetLog());
11243 EXPECT_EQ(ERR_IO_PENDING, rv);
11244 EXPECT_EQ(OK, callback.WaitForResult());
11245
11246 const HttpResponseInfo* response = trans1.GetResponseInfo();
11247 ASSERT_TRUE(response != NULL);
11248 ASSERT_TRUE(response->headers.get() != NULL);
11249 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11250
11251 std::string response_data;
11252 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
11253 EXPECT_EQ("hello!", response_data);
11254
11255 // Preload cache entries into HostCache.
11256 HostResolver::RequestInfo resolve_info(HostPortPair("www.gmail.com", 443));
11257 AddressList ignored;
11258 rv = host_resolver.Resolve(resolve_info,
11259 DEFAULT_PRIORITY,
11260 &ignored,
11261 callback.callback(),
11262 NULL,
11263 BoundNetLog());
11264 EXPECT_EQ(ERR_IO_PENDING, rv);
11265 rv = callback.WaitForResult();
11266 EXPECT_EQ(OK, rv);
11267
11268 HttpRequestInfo request2;
11269 request2.method = "GET";
11270 request2.url = GURL("https://www.gmail.com/");
11271 request2.load_flags = 0;
11272 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
11273
11274 rv = trans2.Start(&request2, callback.callback(), BoundNetLog());
11275 EXPECT_EQ(ERR_IO_PENDING, rv);
11276 EXPECT_EQ(OK, callback.WaitForResult());
11277
11278 response = trans2.GetResponseInfo();
11279 ASSERT_TRUE(response != NULL);
11280 ASSERT_TRUE(response->headers.get() != NULL);
11281 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11282 EXPECT_TRUE(response->was_fetched_via_spdy);
11283 EXPECT_TRUE(response->was_npn_negotiated);
11284 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
11285 EXPECT_EQ("hello!", response_data);
11286 #endif
11287 }
11288 #undef MAYBE_UseIPConnectionPoolingWithHostCacheExpiration
11289
TEST_P(HttpNetworkTransactionTest,DoNotUseSpdySessionForHttp)11290 TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttp) {
11291 const std::string https_url = "https://www.google.com/";
11292 const std::string http_url = "http://www.google.com:443/";
11293
11294 // SPDY GET for HTTPS URL
11295 scoped_ptr<SpdyFrame> req1(
11296 spdy_util_.ConstructSpdyGet(https_url.c_str(), false, 1, LOWEST));
11297
11298 MockWrite writes1[] = {
11299 CreateMockWrite(*req1, 0),
11300 };
11301
11302 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11303 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
11304 MockRead reads1[] = {
11305 CreateMockRead(*resp1, 1),
11306 CreateMockRead(*body1, 2),
11307 MockRead(ASYNC, ERR_IO_PENDING, 3)
11308 };
11309
11310 DelayedSocketData data1(
11311 1, reads1, arraysize(reads1),
11312 writes1, arraysize(writes1));
11313 MockConnect connect_data1(ASYNC, OK);
11314 data1.set_connect_data(connect_data1);
11315
11316 // HTTP GET for the HTTP URL
11317 MockWrite writes2[] = {
11318 MockWrite(ASYNC, 4,
11319 "GET / HTTP/1.1\r\n"
11320 "Host: www.google.com:443\r\n"
11321 "Connection: keep-alive\r\n\r\n"),
11322 };
11323
11324 MockRead reads2[] = {
11325 MockRead(ASYNC, 5, "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
11326 MockRead(ASYNC, 6, "hello"),
11327 MockRead(ASYNC, 7, OK),
11328 };
11329
11330 DelayedSocketData data2(
11331 1, reads2, arraysize(reads2),
11332 writes2, arraysize(writes2));
11333
11334 SSLSocketDataProvider ssl(ASYNC, OK);
11335 ssl.SetNextProto(GetParam());
11336 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11337 session_deps_.socket_factory->AddSocketDataProvider(&data1);
11338 session_deps_.socket_factory->AddSocketDataProvider(&data2);
11339
11340 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11341
11342 // Start the first transaction to set up the SpdySession
11343 HttpRequestInfo request1;
11344 request1.method = "GET";
11345 request1.url = GURL(https_url);
11346 request1.load_flags = 0;
11347 HttpNetworkTransaction trans1(LOWEST, session.get());
11348 TestCompletionCallback callback1;
11349 EXPECT_EQ(ERR_IO_PENDING,
11350 trans1.Start(&request1, callback1.callback(), BoundNetLog()));
11351 base::MessageLoop::current()->RunUntilIdle();
11352
11353 EXPECT_EQ(OK, callback1.WaitForResult());
11354 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
11355
11356 // Now, start the HTTP request
11357 HttpRequestInfo request2;
11358 request2.method = "GET";
11359 request2.url = GURL(http_url);
11360 request2.load_flags = 0;
11361 HttpNetworkTransaction trans2(MEDIUM, session.get());
11362 TestCompletionCallback callback2;
11363 EXPECT_EQ(ERR_IO_PENDING,
11364 trans2.Start(&request2, callback2.callback(), BoundNetLog()));
11365 base::MessageLoop::current()->RunUntilIdle();
11366
11367 EXPECT_EQ(OK, callback2.WaitForResult());
11368 EXPECT_FALSE(trans2.GetResponseInfo()->was_fetched_via_spdy);
11369 }
11370
TEST_P(HttpNetworkTransactionTest,DoNotUseSpdySessionForHttpOverTunnel)11371 TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttpOverTunnel) {
11372 const std::string https_url = "https://www.google.com/";
11373 const std::string http_url = "http://www.google.com:443/";
11374
11375 // SPDY GET for HTTPS URL (through CONNECT tunnel)
11376 scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(NULL, 0, 1,
11377 LOWEST));
11378 scoped_ptr<SpdyFrame> req1(
11379 spdy_util_.ConstructSpdyGet(https_url.c_str(), false, 1, LOWEST));
11380 scoped_ptr<SpdyFrame> wrapped_req1(
11381 spdy_util_.ConstructWrappedSpdyFrame(req1, 1));
11382
11383 // SPDY GET for HTTP URL (through the proxy, but not the tunnel).
11384 SpdySynStreamIR req2_ir(3);
11385 spdy_util_.SetPriority(MEDIUM, &req2_ir);
11386 req2_ir.set_fin(true);
11387 req2_ir.SetHeader(spdy_util_.GetMethodKey(), "GET");
11388 req2_ir.SetHeader(spdy_util_.GetPathKey(),
11389 spdy_util_.is_spdy2() ? http_url.c_str() : "/");
11390 req2_ir.SetHeader(spdy_util_.GetHostKey(), "www.google.com:443");
11391 req2_ir.SetHeader(spdy_util_.GetSchemeKey(), "http");
11392 spdy_util_.MaybeAddVersionHeader(&req2_ir);
11393 scoped_ptr<SpdyFrame> req2(
11394 spdy_util_.CreateFramer(false)->SerializeFrame(req2_ir));
11395
11396 MockWrite writes1[] = {
11397 CreateMockWrite(*connect, 0),
11398 CreateMockWrite(*wrapped_req1, 2),
11399 CreateMockWrite(*req2, 5),
11400 };
11401
11402 scoped_ptr<SpdyFrame> conn_resp(
11403 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11404 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11405 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
11406 scoped_ptr<SpdyFrame> wrapped_resp1(
11407 spdy_util_.ConstructWrappedSpdyFrame(resp1, 1));
11408 scoped_ptr<SpdyFrame> wrapped_body1(
11409 spdy_util_.ConstructWrappedSpdyFrame(body1, 1));
11410 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
11411 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, true));
11412 MockRead reads1[] = {
11413 CreateMockRead(*conn_resp, 1),
11414 CreateMockRead(*wrapped_resp1, 3),
11415 CreateMockRead(*wrapped_body1, 4),
11416 CreateMockRead(*resp2, 6),
11417 CreateMockRead(*body2, 7),
11418 MockRead(ASYNC, ERR_IO_PENDING, 8)
11419 };
11420
11421 DeterministicSocketData data1(reads1, arraysize(reads1),
11422 writes1, arraysize(writes1));
11423 MockConnect connect_data1(ASYNC, OK);
11424 data1.set_connect_data(connect_data1);
11425
11426 session_deps_.proxy_service.reset(
11427 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
11428 CapturingNetLog log;
11429 session_deps_.net_log = &log;
11430 SSLSocketDataProvider ssl1(ASYNC, OK); // to the proxy
11431 ssl1.SetNextProto(GetParam());
11432 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl1);
11433 SSLSocketDataProvider ssl2(ASYNC, OK); // to the server
11434 ssl2.SetNextProto(GetParam());
11435 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2);
11436 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data1);
11437
11438 scoped_refptr<HttpNetworkSession> session(
11439 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
11440
11441 // Start the first transaction to set up the SpdySession
11442 HttpRequestInfo request1;
11443 request1.method = "GET";
11444 request1.url = GURL(https_url);
11445 request1.load_flags = 0;
11446 HttpNetworkTransaction trans1(LOWEST, session.get());
11447 TestCompletionCallback callback1;
11448 EXPECT_EQ(ERR_IO_PENDING,
11449 trans1.Start(&request1, callback1.callback(), BoundNetLog()));
11450 base::MessageLoop::current()->RunUntilIdle();
11451 data1.RunFor(4);
11452
11453 EXPECT_EQ(OK, callback1.WaitForResult());
11454 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
11455
11456 LoadTimingInfo load_timing_info1;
11457 EXPECT_TRUE(trans1.GetLoadTimingInfo(&load_timing_info1));
11458 TestLoadTimingNotReusedWithPac(load_timing_info1,
11459 CONNECT_TIMING_HAS_SSL_TIMES);
11460
11461 // Now, start the HTTP request
11462 HttpRequestInfo request2;
11463 request2.method = "GET";
11464 request2.url = GURL(http_url);
11465 request2.load_flags = 0;
11466 HttpNetworkTransaction trans2(MEDIUM, session.get());
11467 TestCompletionCallback callback2;
11468 EXPECT_EQ(ERR_IO_PENDING,
11469 trans2.Start(&request2, callback2.callback(), BoundNetLog()));
11470 base::MessageLoop::current()->RunUntilIdle();
11471 data1.RunFor(3);
11472
11473 EXPECT_EQ(OK, callback2.WaitForResult());
11474 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
11475
11476 LoadTimingInfo load_timing_info2;
11477 EXPECT_TRUE(trans2.GetLoadTimingInfo(&load_timing_info2));
11478 // The established SPDY sessions is considered reused by the HTTP request.
11479 TestLoadTimingReusedWithPac(load_timing_info2);
11480 // HTTP requests over a SPDY session should have a different connection
11481 // socket_log_id than requests over a tunnel.
11482 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
11483 }
11484
TEST_P(HttpNetworkTransactionTest,UseSpdySessionForHttpWhenForced)11485 TEST_P(HttpNetworkTransactionTest, UseSpdySessionForHttpWhenForced) {
11486 session_deps_.force_spdy_always = true;
11487 const std::string https_url = "https://www.google.com/";
11488 const std::string http_url = "http://www.google.com:443/";
11489
11490 // SPDY GET for HTTPS URL
11491 scoped_ptr<SpdyFrame> req1(
11492 spdy_util_.ConstructSpdyGet(https_url.c_str(), false, 1, LOWEST));
11493 // SPDY GET for the HTTP URL
11494 scoped_ptr<SpdyFrame> req2(
11495 spdy_util_.ConstructSpdyGet(http_url.c_str(), false, 3, MEDIUM));
11496
11497 MockWrite writes[] = {
11498 CreateMockWrite(*req1, 1),
11499 CreateMockWrite(*req2, 4),
11500 };
11501
11502 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11503 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
11504 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
11505 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, true));
11506 MockRead reads[] = {
11507 CreateMockRead(*resp1, 2),
11508 CreateMockRead(*body1, 3),
11509 CreateMockRead(*resp2, 5),
11510 CreateMockRead(*body2, 6),
11511 MockRead(ASYNC, ERR_IO_PENDING, 7)
11512 };
11513
11514 OrderedSocketData data(reads, arraysize(reads),
11515 writes, arraysize(writes));
11516
11517 SSLSocketDataProvider ssl(ASYNC, OK);
11518 ssl.SetNextProto(GetParam());
11519 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11520 session_deps_.socket_factory->AddSocketDataProvider(&data);
11521
11522 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11523
11524 // Start the first transaction to set up the SpdySession
11525 HttpRequestInfo request1;
11526 request1.method = "GET";
11527 request1.url = GURL(https_url);
11528 request1.load_flags = 0;
11529 HttpNetworkTransaction trans1(LOWEST, session.get());
11530 TestCompletionCallback callback1;
11531 EXPECT_EQ(ERR_IO_PENDING,
11532 trans1.Start(&request1, callback1.callback(), BoundNetLog()));
11533 base::MessageLoop::current()->RunUntilIdle();
11534
11535 EXPECT_EQ(OK, callback1.WaitForResult());
11536 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
11537
11538 // Now, start the HTTP request
11539 HttpRequestInfo request2;
11540 request2.method = "GET";
11541 request2.url = GURL(http_url);
11542 request2.load_flags = 0;
11543 HttpNetworkTransaction trans2(MEDIUM, session.get());
11544 TestCompletionCallback callback2;
11545 EXPECT_EQ(ERR_IO_PENDING,
11546 trans2.Start(&request2, callback2.callback(), BoundNetLog()));
11547 base::MessageLoop::current()->RunUntilIdle();
11548
11549 EXPECT_EQ(OK, callback2.WaitForResult());
11550 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
11551 }
11552
11553 // Test that in the case where we have a SPDY session to a SPDY proxy
11554 // that we do not pool other origins that resolve to the same IP when
11555 // the certificate does not match the new origin.
11556 // http://crbug.com/134690
TEST_P(HttpNetworkTransactionTest,DoNotUseSpdySessionIfCertDoesNotMatch)11557 TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionIfCertDoesNotMatch) {
11558 const std::string url1 = "http://www.google.com/";
11559 const std::string url2 = "https://mail.google.com/";
11560 const std::string ip_addr = "1.2.3.4";
11561
11562 // SPDY GET for HTTP URL (through SPDY proxy)
11563 scoped_ptr<SpdyHeaderBlock> headers(
11564 spdy_util_.ConstructGetHeaderBlockForProxy("http://www.google.com/"));
11565 scoped_ptr<SpdyFrame> req1(spdy_util_.ConstructSpdyControlFrame(
11566 headers.Pass(), false, 1, LOWEST, SYN_STREAM, CONTROL_FLAG_FIN, 0));
11567
11568 MockWrite writes1[] = {
11569 CreateMockWrite(*req1, 0),
11570 };
11571
11572 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11573 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
11574 MockRead reads1[] = {
11575 CreateMockRead(*resp1, 1),
11576 CreateMockRead(*body1, 2),
11577 MockRead(ASYNC, OK, 3) // EOF
11578 };
11579
11580 scoped_ptr<DeterministicSocketData> data1(
11581 new DeterministicSocketData(reads1, arraysize(reads1),
11582 writes1, arraysize(writes1)));
11583 IPAddressNumber ip;
11584 ASSERT_TRUE(ParseIPLiteralToNumber(ip_addr, &ip));
11585 IPEndPoint peer_addr = IPEndPoint(ip, 443);
11586 MockConnect connect_data1(ASYNC, OK, peer_addr);
11587 data1->set_connect_data(connect_data1);
11588
11589 // SPDY GET for HTTPS URL (direct)
11590 scoped_ptr<SpdyFrame> req2(
11591 spdy_util_.ConstructSpdyGet(url2.c_str(), false, 1, MEDIUM));
11592
11593 MockWrite writes2[] = {
11594 CreateMockWrite(*req2, 0),
11595 };
11596
11597 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11598 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
11599 MockRead reads2[] = {
11600 CreateMockRead(*resp2, 1),
11601 CreateMockRead(*body2, 2),
11602 MockRead(ASYNC, OK, 3) // EOF
11603 };
11604
11605 scoped_ptr<DeterministicSocketData> data2(
11606 new DeterministicSocketData(reads2, arraysize(reads2),
11607 writes2, arraysize(writes2)));
11608 MockConnect connect_data2(ASYNC, OK);
11609 data2->set_connect_data(connect_data2);
11610
11611 // Set up a proxy config that sends HTTP requests to a proxy, and
11612 // all others direct.
11613 ProxyConfig proxy_config;
11614 proxy_config.proxy_rules().ParseFromString("http=https://proxy:443");
11615 CapturingProxyResolver* capturing_proxy_resolver =
11616 new CapturingProxyResolver();
11617 session_deps_.proxy_service.reset(new ProxyService(
11618 new ProxyConfigServiceFixed(proxy_config), capturing_proxy_resolver,
11619 NULL));
11620
11621 // Load a valid cert. Note, that this does not need to
11622 // be valid for proxy because the MockSSLClientSocket does
11623 // not actually verify it. But SpdySession will use this
11624 // to see if it is valid for the new origin
11625 base::FilePath certs_dir = GetTestCertsDirectory();
11626 scoped_refptr<X509Certificate> server_cert(
11627 ImportCertFromFile(certs_dir, "ok_cert.pem"));
11628 ASSERT_NE(static_cast<X509Certificate*>(NULL), server_cert);
11629
11630 SSLSocketDataProvider ssl1(ASYNC, OK); // to the proxy
11631 ssl1.SetNextProto(GetParam());
11632 ssl1.cert = server_cert;
11633 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl1);
11634 session_deps_.deterministic_socket_factory->AddSocketDataProvider(
11635 data1.get());
11636
11637 SSLSocketDataProvider ssl2(ASYNC, OK); // to the server
11638 ssl2.SetNextProto(GetParam());
11639 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2);
11640 session_deps_.deterministic_socket_factory->AddSocketDataProvider(
11641 data2.get());
11642
11643 session_deps_.host_resolver.reset(new MockCachingHostResolver());
11644 session_deps_.host_resolver->rules()->AddRule("mail.google.com", ip_addr);
11645 session_deps_.host_resolver->rules()->AddRule("proxy", ip_addr);
11646
11647 scoped_refptr<HttpNetworkSession> session(
11648 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
11649
11650 // Start the first transaction to set up the SpdySession
11651 HttpRequestInfo request1;
11652 request1.method = "GET";
11653 request1.url = GURL(url1);
11654 request1.load_flags = 0;
11655 HttpNetworkTransaction trans1(LOWEST, session.get());
11656 TestCompletionCallback callback1;
11657 ASSERT_EQ(ERR_IO_PENDING,
11658 trans1.Start(&request1, callback1.callback(), BoundNetLog()));
11659 data1->RunFor(3);
11660
11661 ASSERT_TRUE(callback1.have_result());
11662 EXPECT_EQ(OK, callback1.WaitForResult());
11663 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
11664
11665 // Now, start the HTTP request
11666 HttpRequestInfo request2;
11667 request2.method = "GET";
11668 request2.url = GURL(url2);
11669 request2.load_flags = 0;
11670 HttpNetworkTransaction trans2(MEDIUM, session.get());
11671 TestCompletionCallback callback2;
11672 EXPECT_EQ(ERR_IO_PENDING,
11673 trans2.Start(&request2, callback2.callback(), BoundNetLog()));
11674 base::MessageLoop::current()->RunUntilIdle();
11675 data2->RunFor(3);
11676
11677 ASSERT_TRUE(callback2.have_result());
11678 EXPECT_EQ(OK, callback2.WaitForResult());
11679 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
11680 }
11681
11682 // Test to verify that a failed socket read (due to an ERR_CONNECTION_CLOSED
11683 // error) in SPDY session, removes the socket from pool and closes the SPDY
11684 // session. Verify that new url's from the same HttpNetworkSession (and a new
11685 // SpdySession) do work. http://crbug.com/224701
TEST_P(HttpNetworkTransactionTest,ErrorSocketNotConnected)11686 TEST_P(HttpNetworkTransactionTest, ErrorSocketNotConnected) {
11687 const std::string https_url = "https://www.google.com/";
11688
11689 MockRead reads1[] = {
11690 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED, 0)
11691 };
11692
11693 scoped_ptr<DeterministicSocketData> data1(
11694 new DeterministicSocketData(reads1, arraysize(reads1), NULL, 0));
11695 data1->SetStop(1);
11696
11697 scoped_ptr<SpdyFrame> req2(
11698 spdy_util_.ConstructSpdyGet(https_url.c_str(), false, 1, MEDIUM));
11699 MockWrite writes2[] = {
11700 CreateMockWrite(*req2, 0),
11701 };
11702
11703 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11704 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
11705 MockRead reads2[] = {
11706 CreateMockRead(*resp2, 1),
11707 CreateMockRead(*body2, 2),
11708 MockRead(ASYNC, OK, 3) // EOF
11709 };
11710
11711 scoped_ptr<DeterministicSocketData> data2(
11712 new DeterministicSocketData(reads2, arraysize(reads2),
11713 writes2, arraysize(writes2)));
11714
11715 SSLSocketDataProvider ssl1(ASYNC, OK);
11716 ssl1.SetNextProto(GetParam());
11717 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl1);
11718 session_deps_.deterministic_socket_factory->AddSocketDataProvider(
11719 data1.get());
11720
11721 SSLSocketDataProvider ssl2(ASYNC, OK);
11722 ssl2.SetNextProto(GetParam());
11723 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2);
11724 session_deps_.deterministic_socket_factory->AddSocketDataProvider(
11725 data2.get());
11726
11727 scoped_refptr<HttpNetworkSession> session(
11728 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
11729
11730 // Start the first transaction to set up the SpdySession and verify that
11731 // connection was closed.
11732 HttpRequestInfo request1;
11733 request1.method = "GET";
11734 request1.url = GURL(https_url);
11735 request1.load_flags = 0;
11736 HttpNetworkTransaction trans1(MEDIUM, session.get());
11737 TestCompletionCallback callback1;
11738 EXPECT_EQ(ERR_IO_PENDING,
11739 trans1.Start(&request1, callback1.callback(), BoundNetLog()));
11740 base::MessageLoop::current()->RunUntilIdle();
11741 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback1.WaitForResult());
11742
11743 // Now, start the second request and make sure it succeeds.
11744 HttpRequestInfo request2;
11745 request2.method = "GET";
11746 request2.url = GURL(https_url);
11747 request2.load_flags = 0;
11748 HttpNetworkTransaction trans2(MEDIUM, session.get());
11749 TestCompletionCallback callback2;
11750 EXPECT_EQ(ERR_IO_PENDING,
11751 trans2.Start(&request2, callback2.callback(), BoundNetLog()));
11752 base::MessageLoop::current()->RunUntilIdle();
11753 data2->RunFor(3);
11754
11755 ASSERT_TRUE(callback2.have_result());
11756 EXPECT_EQ(OK, callback2.WaitForResult());
11757 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
11758 }
11759
TEST_P(HttpNetworkTransactionTest,CloseIdleSpdySessionToOpenNewOne)11760 TEST_P(HttpNetworkTransactionTest, CloseIdleSpdySessionToOpenNewOne) {
11761 session_deps_.next_protos = SpdyNextProtos();
11762 ClientSocketPoolManager::set_max_sockets_per_group(
11763 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
11764 ClientSocketPoolManager::set_max_sockets_per_pool(
11765 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
11766
11767 // Use two different hosts with different IPs so they don't get pooled.
11768 session_deps_.host_resolver->rules()->AddRule("www.a.com", "10.0.0.1");
11769 session_deps_.host_resolver->rules()->AddRule("www.b.com", "10.0.0.2");
11770 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11771
11772 SSLSocketDataProvider ssl1(ASYNC, OK);
11773 ssl1.SetNextProto(GetParam());
11774 SSLSocketDataProvider ssl2(ASYNC, OK);
11775 ssl2.SetNextProto(GetParam());
11776 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
11777 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
11778
11779 scoped_ptr<SpdyFrame> host1_req(spdy_util_.ConstructSpdyGet(
11780 "https://www.a.com", false, 1, DEFAULT_PRIORITY));
11781 MockWrite spdy1_writes[] = {
11782 CreateMockWrite(*host1_req, 1),
11783 };
11784 scoped_ptr<SpdyFrame> host1_resp(
11785 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11786 scoped_ptr<SpdyFrame> host1_resp_body(
11787 spdy_util_.ConstructSpdyBodyFrame(1, true));
11788 MockRead spdy1_reads[] = {
11789 CreateMockRead(*host1_resp, 2),
11790 CreateMockRead(*host1_resp_body, 3),
11791 MockRead(ASYNC, ERR_IO_PENDING, 4),
11792 };
11793
11794 scoped_ptr<OrderedSocketData> spdy1_data(
11795 new OrderedSocketData(
11796 spdy1_reads, arraysize(spdy1_reads),
11797 spdy1_writes, arraysize(spdy1_writes)));
11798 session_deps_.socket_factory->AddSocketDataProvider(spdy1_data.get());
11799
11800 scoped_ptr<SpdyFrame> host2_req(spdy_util_.ConstructSpdyGet(
11801 "https://www.b.com", false, 1, DEFAULT_PRIORITY));
11802 MockWrite spdy2_writes[] = {
11803 CreateMockWrite(*host2_req, 1),
11804 };
11805 scoped_ptr<SpdyFrame> host2_resp(
11806 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11807 scoped_ptr<SpdyFrame> host2_resp_body(
11808 spdy_util_.ConstructSpdyBodyFrame(1, true));
11809 MockRead spdy2_reads[] = {
11810 CreateMockRead(*host2_resp, 2),
11811 CreateMockRead(*host2_resp_body, 3),
11812 MockRead(ASYNC, ERR_IO_PENDING, 4),
11813 };
11814
11815 scoped_ptr<OrderedSocketData> spdy2_data(
11816 new OrderedSocketData(
11817 spdy2_reads, arraysize(spdy2_reads),
11818 spdy2_writes, arraysize(spdy2_writes)));
11819 session_deps_.socket_factory->AddSocketDataProvider(spdy2_data.get());
11820
11821 MockWrite http_write[] = {
11822 MockWrite("GET / HTTP/1.1\r\n"
11823 "Host: www.a.com\r\n"
11824 "Connection: keep-alive\r\n\r\n"),
11825 };
11826
11827 MockRead http_read[] = {
11828 MockRead("HTTP/1.1 200 OK\r\n"),
11829 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11830 MockRead("Content-Length: 6\r\n\r\n"),
11831 MockRead("hello!"),
11832 };
11833 StaticSocketDataProvider http_data(http_read, arraysize(http_read),
11834 http_write, arraysize(http_write));
11835 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
11836
11837 HostPortPair host_port_pair_a("www.a.com", 443);
11838 SpdySessionKey spdy_session_key_a(
11839 host_port_pair_a, ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
11840 EXPECT_FALSE(
11841 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
11842
11843 TestCompletionCallback callback;
11844 HttpRequestInfo request1;
11845 request1.method = "GET";
11846 request1.url = GURL("https://www.a.com/");
11847 request1.load_flags = 0;
11848 scoped_ptr<HttpNetworkTransaction> trans(
11849 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
11850
11851 int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
11852 EXPECT_EQ(ERR_IO_PENDING, rv);
11853 EXPECT_EQ(OK, callback.WaitForResult());
11854
11855 const HttpResponseInfo* response = trans->GetResponseInfo();
11856 ASSERT_TRUE(response != NULL);
11857 ASSERT_TRUE(response->headers.get() != NULL);
11858 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11859 EXPECT_TRUE(response->was_fetched_via_spdy);
11860 EXPECT_TRUE(response->was_npn_negotiated);
11861
11862 std::string response_data;
11863 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
11864 EXPECT_EQ("hello!", response_data);
11865 trans.reset();
11866 EXPECT_TRUE(
11867 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
11868
11869 HostPortPair host_port_pair_b("www.b.com", 443);
11870 SpdySessionKey spdy_session_key_b(
11871 host_port_pair_b, ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
11872 EXPECT_FALSE(
11873 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
11874 HttpRequestInfo request2;
11875 request2.method = "GET";
11876 request2.url = GURL("https://www.b.com/");
11877 request2.load_flags = 0;
11878 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
11879
11880 rv = trans->Start(&request2, callback.callback(), BoundNetLog());
11881 EXPECT_EQ(ERR_IO_PENDING, rv);
11882 EXPECT_EQ(OK, callback.WaitForResult());
11883
11884 response = trans->GetResponseInfo();
11885 ASSERT_TRUE(response != NULL);
11886 ASSERT_TRUE(response->headers.get() != NULL);
11887 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11888 EXPECT_TRUE(response->was_fetched_via_spdy);
11889 EXPECT_TRUE(response->was_npn_negotiated);
11890 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
11891 EXPECT_EQ("hello!", response_data);
11892 EXPECT_FALSE(
11893 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
11894 EXPECT_TRUE(
11895 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
11896
11897 HostPortPair host_port_pair_a1("www.a.com", 80);
11898 SpdySessionKey spdy_session_key_a1(
11899 host_port_pair_a1, ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
11900 EXPECT_FALSE(
11901 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a1));
11902 HttpRequestInfo request3;
11903 request3.method = "GET";
11904 request3.url = GURL("http://www.a.com/");
11905 request3.load_flags = 0;
11906 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
11907
11908 rv = trans->Start(&request3, callback.callback(), BoundNetLog());
11909 EXPECT_EQ(ERR_IO_PENDING, rv);
11910 EXPECT_EQ(OK, callback.WaitForResult());
11911
11912 response = trans->GetResponseInfo();
11913 ASSERT_TRUE(response != NULL);
11914 ASSERT_TRUE(response->headers.get() != NULL);
11915 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11916 EXPECT_FALSE(response->was_fetched_via_spdy);
11917 EXPECT_FALSE(response->was_npn_negotiated);
11918 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
11919 EXPECT_EQ("hello!", response_data);
11920 EXPECT_FALSE(
11921 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
11922 EXPECT_FALSE(
11923 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
11924 }
11925
TEST_P(HttpNetworkTransactionTest,HttpSyncConnectError)11926 TEST_P(HttpNetworkTransactionTest, HttpSyncConnectError) {
11927 HttpRequestInfo request;
11928 request.method = "GET";
11929 request.url = GURL("http://www.google.com/");
11930 request.load_flags = 0;
11931
11932 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11933 scoped_ptr<HttpTransaction> trans(
11934 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
11935
11936 MockConnect mock_connect(SYNCHRONOUS, ERR_CONNECTION_REFUSED);
11937 StaticSocketDataProvider data;
11938 data.set_connect_data(mock_connect);
11939 session_deps_.socket_factory->AddSocketDataProvider(&data);
11940
11941 TestCompletionCallback callback;
11942
11943 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
11944 EXPECT_EQ(ERR_IO_PENDING, rv);
11945
11946 rv = callback.WaitForResult();
11947 EXPECT_EQ(ERR_CONNECTION_REFUSED, rv);
11948
11949 EXPECT_EQ(NULL, trans->GetResponseInfo());
11950
11951 // We don't care whether this succeeds or fails, but it shouldn't crash.
11952 HttpRequestHeaders request_headers;
11953 trans->GetFullRequestHeaders(&request_headers);
11954 }
11955
TEST_P(HttpNetworkTransactionTest,HttpAsyncConnectError)11956 TEST_P(HttpNetworkTransactionTest, HttpAsyncConnectError) {
11957 HttpRequestInfo request;
11958 request.method = "GET";
11959 request.url = GURL("http://www.google.com/");
11960 request.load_flags = 0;
11961
11962 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11963 scoped_ptr<HttpTransaction> trans(
11964 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
11965
11966 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
11967 StaticSocketDataProvider data;
11968 data.set_connect_data(mock_connect);
11969 session_deps_.socket_factory->AddSocketDataProvider(&data);
11970
11971 TestCompletionCallback callback;
11972
11973 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
11974 EXPECT_EQ(ERR_IO_PENDING, rv);
11975
11976 rv = callback.WaitForResult();
11977 EXPECT_EQ(ERR_CONNECTION_REFUSED, rv);
11978
11979 EXPECT_EQ(NULL, trans->GetResponseInfo());
11980
11981 // We don't care whether this succeeds or fails, but it shouldn't crash.
11982 HttpRequestHeaders request_headers;
11983 trans->GetFullRequestHeaders(&request_headers);
11984 }
11985
TEST_P(HttpNetworkTransactionTest,HttpSyncWriteError)11986 TEST_P(HttpNetworkTransactionTest, HttpSyncWriteError) {
11987 HttpRequestInfo request;
11988 request.method = "GET";
11989 request.url = GURL("http://www.google.com/");
11990 request.load_flags = 0;
11991
11992 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11993 scoped_ptr<HttpTransaction> trans(
11994 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
11995
11996 MockWrite data_writes[] = {
11997 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
11998 };
11999 MockRead data_reads[] = {
12000 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
12001 };
12002
12003 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
12004 data_writes, arraysize(data_writes));
12005 session_deps_.socket_factory->AddSocketDataProvider(&data);
12006
12007 TestCompletionCallback callback;
12008
12009 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
12010 EXPECT_EQ(ERR_IO_PENDING, rv);
12011
12012 rv = callback.WaitForResult();
12013 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
12014
12015 EXPECT_EQ(NULL, trans->GetResponseInfo());
12016
12017 HttpRequestHeaders request_headers;
12018 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
12019 EXPECT_TRUE(request_headers.HasHeader("Host"));
12020 }
12021
TEST_P(HttpNetworkTransactionTest,HttpAsyncWriteError)12022 TEST_P(HttpNetworkTransactionTest, HttpAsyncWriteError) {
12023 HttpRequestInfo request;
12024 request.method = "GET";
12025 request.url = GURL("http://www.google.com/");
12026 request.load_flags = 0;
12027
12028 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12029 scoped_ptr<HttpTransaction> trans(
12030 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
12031
12032 MockWrite data_writes[] = {
12033 MockWrite(ASYNC, ERR_CONNECTION_RESET),
12034 };
12035 MockRead data_reads[] = {
12036 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
12037 };
12038
12039 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
12040 data_writes, arraysize(data_writes));
12041 session_deps_.socket_factory->AddSocketDataProvider(&data);
12042
12043 TestCompletionCallback callback;
12044
12045 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
12046 EXPECT_EQ(ERR_IO_PENDING, rv);
12047
12048 rv = callback.WaitForResult();
12049 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
12050
12051 EXPECT_EQ(NULL, trans->GetResponseInfo());
12052
12053 HttpRequestHeaders request_headers;
12054 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
12055 EXPECT_TRUE(request_headers.HasHeader("Host"));
12056 }
12057
TEST_P(HttpNetworkTransactionTest,HttpSyncReadError)12058 TEST_P(HttpNetworkTransactionTest, HttpSyncReadError) {
12059 HttpRequestInfo request;
12060 request.method = "GET";
12061 request.url = GURL("http://www.google.com/");
12062 request.load_flags = 0;
12063
12064 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12065 scoped_ptr<HttpTransaction> trans(
12066 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
12067
12068 MockWrite data_writes[] = {
12069 MockWrite("GET / HTTP/1.1\r\n"
12070 "Host: www.google.com\r\n"
12071 "Connection: keep-alive\r\n\r\n"),
12072 };
12073 MockRead data_reads[] = {
12074 MockRead(SYNCHRONOUS, ERR_CONNECTION_RESET),
12075 };
12076
12077 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
12078 data_writes, arraysize(data_writes));
12079 session_deps_.socket_factory->AddSocketDataProvider(&data);
12080
12081 TestCompletionCallback callback;
12082
12083 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
12084 EXPECT_EQ(ERR_IO_PENDING, rv);
12085
12086 rv = callback.WaitForResult();
12087 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
12088
12089 EXPECT_EQ(NULL, trans->GetResponseInfo());
12090
12091 HttpRequestHeaders request_headers;
12092 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
12093 EXPECT_TRUE(request_headers.HasHeader("Host"));
12094 }
12095
TEST_P(HttpNetworkTransactionTest,HttpAsyncReadError)12096 TEST_P(HttpNetworkTransactionTest, HttpAsyncReadError) {
12097 HttpRequestInfo request;
12098 request.method = "GET";
12099 request.url = GURL("http://www.google.com/");
12100 request.load_flags = 0;
12101
12102 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12103 scoped_ptr<HttpTransaction> trans(
12104 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
12105
12106 MockWrite data_writes[] = {
12107 MockWrite("GET / HTTP/1.1\r\n"
12108 "Host: www.google.com\r\n"
12109 "Connection: keep-alive\r\n\r\n"),
12110 };
12111 MockRead data_reads[] = {
12112 MockRead(ASYNC, ERR_CONNECTION_RESET),
12113 };
12114
12115 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
12116 data_writes, arraysize(data_writes));
12117 session_deps_.socket_factory->AddSocketDataProvider(&data);
12118
12119 TestCompletionCallback callback;
12120
12121 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
12122 EXPECT_EQ(ERR_IO_PENDING, rv);
12123
12124 rv = callback.WaitForResult();
12125 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
12126
12127 EXPECT_EQ(NULL, trans->GetResponseInfo());
12128
12129 HttpRequestHeaders request_headers;
12130 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
12131 EXPECT_TRUE(request_headers.HasHeader("Host"));
12132 }
12133
TEST_P(HttpNetworkTransactionTest,GetFullRequestHeadersIncludesExtraHeader)12134 TEST_P(HttpNetworkTransactionTest, GetFullRequestHeadersIncludesExtraHeader) {
12135 HttpRequestInfo request;
12136 request.method = "GET";
12137 request.url = GURL("http://www.google.com/");
12138 request.load_flags = 0;
12139 request.extra_headers.SetHeader("X-Foo", "bar");
12140
12141 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12142 scoped_ptr<HttpTransaction> trans(
12143 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
12144
12145 MockWrite data_writes[] = {
12146 MockWrite("GET / HTTP/1.1\r\n"
12147 "Host: www.google.com\r\n"
12148 "Connection: keep-alive\r\n"
12149 "X-Foo: bar\r\n\r\n"),
12150 };
12151 MockRead data_reads[] = {
12152 MockRead("HTTP/1.1 200 OK\r\n"
12153 "Content-Length: 5\r\n\r\n"
12154 "hello"),
12155 MockRead(ASYNC, ERR_UNEXPECTED),
12156 };
12157
12158 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
12159 data_writes, arraysize(data_writes));
12160 session_deps_.socket_factory->AddSocketDataProvider(&data);
12161
12162 TestCompletionCallback callback;
12163
12164 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
12165 EXPECT_EQ(ERR_IO_PENDING, rv);
12166
12167 rv = callback.WaitForResult();
12168 EXPECT_EQ(OK, rv);
12169
12170 HttpRequestHeaders request_headers;
12171 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
12172 std::string foo;
12173 EXPECT_TRUE(request_headers.GetHeader("X-Foo", &foo));
12174 EXPECT_EQ("bar", foo);
12175 }
12176
12177 namespace {
12178
12179 // Fake HttpStreamBase that simply records calls to SetPriority().
12180 class FakeStream : public HttpStreamBase,
12181 public base::SupportsWeakPtr<FakeStream> {
12182 public:
FakeStream(RequestPriority priority)12183 explicit FakeStream(RequestPriority priority) : priority_(priority) {}
~FakeStream()12184 virtual ~FakeStream() {}
12185
priority() const12186 RequestPriority priority() const { return priority_; }
12187
InitializeStream(const HttpRequestInfo * request_info,RequestPriority priority,const BoundNetLog & net_log,const CompletionCallback & callback)12188 virtual int InitializeStream(const HttpRequestInfo* request_info,
12189 RequestPriority priority,
12190 const BoundNetLog& net_log,
12191 const CompletionCallback& callback) OVERRIDE {
12192 return ERR_IO_PENDING;
12193 }
12194
SendRequest(const HttpRequestHeaders & request_headers,HttpResponseInfo * response,const CompletionCallback & callback)12195 virtual int SendRequest(const HttpRequestHeaders& request_headers,
12196 HttpResponseInfo* response,
12197 const CompletionCallback& callback) OVERRIDE {
12198 ADD_FAILURE();
12199 return ERR_UNEXPECTED;
12200 }
12201
ReadResponseHeaders(const CompletionCallback & callback)12202 virtual int ReadResponseHeaders(const CompletionCallback& callback) OVERRIDE {
12203 ADD_FAILURE();
12204 return ERR_UNEXPECTED;
12205 }
12206
ReadResponseBody(IOBuffer * buf,int buf_len,const CompletionCallback & callback)12207 virtual int ReadResponseBody(IOBuffer* buf, int buf_len,
12208 const CompletionCallback& callback) OVERRIDE {
12209 ADD_FAILURE();
12210 return ERR_UNEXPECTED;
12211 }
12212
Close(bool not_reusable)12213 virtual void Close(bool not_reusable) OVERRIDE {}
12214
IsResponseBodyComplete() const12215 virtual bool IsResponseBodyComplete() const OVERRIDE {
12216 ADD_FAILURE();
12217 return false;
12218 }
12219
CanFindEndOfResponse() const12220 virtual bool CanFindEndOfResponse() const OVERRIDE {
12221 return false;
12222 }
12223
IsConnectionReused() const12224 virtual bool IsConnectionReused() const OVERRIDE {
12225 ADD_FAILURE();
12226 return false;
12227 }
12228
SetConnectionReused()12229 virtual void SetConnectionReused() OVERRIDE {
12230 ADD_FAILURE();
12231 }
12232
IsConnectionReusable() const12233 virtual bool IsConnectionReusable() const OVERRIDE {
12234 ADD_FAILURE();
12235 return false;
12236 }
12237
GetTotalReceivedBytes() const12238 virtual int64 GetTotalReceivedBytes() const OVERRIDE {
12239 ADD_FAILURE();
12240 return 0;
12241 }
12242
GetLoadTimingInfo(LoadTimingInfo * load_timing_info) const12243 virtual bool GetLoadTimingInfo(
12244 LoadTimingInfo* load_timing_info) const OVERRIDE {
12245 ADD_FAILURE();
12246 return false;
12247 }
12248
GetSSLInfo(SSLInfo * ssl_info)12249 virtual void GetSSLInfo(SSLInfo* ssl_info) OVERRIDE {
12250 ADD_FAILURE();
12251 }
12252
GetSSLCertRequestInfo(SSLCertRequestInfo * cert_request_info)12253 virtual void GetSSLCertRequestInfo(
12254 SSLCertRequestInfo* cert_request_info) OVERRIDE {
12255 ADD_FAILURE();
12256 }
12257
IsSpdyHttpStream() const12258 virtual bool IsSpdyHttpStream() const OVERRIDE {
12259 ADD_FAILURE();
12260 return false;
12261 }
12262
Drain(HttpNetworkSession * session)12263 virtual void Drain(HttpNetworkSession* session) OVERRIDE {
12264 ADD_FAILURE();
12265 }
12266
SetPriority(RequestPriority priority)12267 virtual void SetPriority(RequestPriority priority) OVERRIDE {
12268 priority_ = priority;
12269 }
12270
12271 private:
12272 RequestPriority priority_;
12273
12274 DISALLOW_COPY_AND_ASSIGN(FakeStream);
12275 };
12276
12277 // Fake HttpStreamRequest that simply records calls to SetPriority()
12278 // and vends FakeStreams with its current priority.
12279 class FakeStreamRequest : public HttpStreamRequest,
12280 public base::SupportsWeakPtr<FakeStreamRequest> {
12281 public:
FakeStreamRequest(RequestPriority priority,HttpStreamRequest::Delegate * delegate)12282 FakeStreamRequest(RequestPriority priority,
12283 HttpStreamRequest::Delegate* delegate)
12284 : priority_(priority),
12285 delegate_(delegate),
12286 websocket_stream_create_helper_(NULL) {}
12287
FakeStreamRequest(RequestPriority priority,HttpStreamRequest::Delegate * delegate,WebSocketHandshakeStreamBase::CreateHelper * create_helper)12288 FakeStreamRequest(RequestPriority priority,
12289 HttpStreamRequest::Delegate* delegate,
12290 WebSocketHandshakeStreamBase::CreateHelper* create_helper)
12291 : priority_(priority),
12292 delegate_(delegate),
12293 websocket_stream_create_helper_(create_helper) {}
12294
~FakeStreamRequest()12295 virtual ~FakeStreamRequest() {}
12296
priority() const12297 RequestPriority priority() const { return priority_; }
12298
12299 const WebSocketHandshakeStreamBase::CreateHelper*
websocket_stream_create_helper() const12300 websocket_stream_create_helper() const {
12301 return websocket_stream_create_helper_;
12302 }
12303
12304 // Create a new FakeStream and pass it to the request's
12305 // delegate. Returns a weak pointer to the FakeStream.
FinishStreamRequest()12306 base::WeakPtr<FakeStream> FinishStreamRequest() {
12307 FakeStream* fake_stream = new FakeStream(priority_);
12308 // Do this before calling OnStreamReady() as OnStreamReady() may
12309 // immediately delete |fake_stream|.
12310 base::WeakPtr<FakeStream> weak_stream = fake_stream->AsWeakPtr();
12311 delegate_->OnStreamReady(SSLConfig(), ProxyInfo(), fake_stream);
12312 return weak_stream;
12313 }
12314
RestartTunnelWithProxyAuth(const AuthCredentials & credentials)12315 virtual int RestartTunnelWithProxyAuth(
12316 const AuthCredentials& credentials) OVERRIDE {
12317 ADD_FAILURE();
12318 return ERR_UNEXPECTED;
12319 }
12320
GetLoadState() const12321 virtual LoadState GetLoadState() const OVERRIDE {
12322 ADD_FAILURE();
12323 return LoadState();
12324 }
12325
SetPriority(RequestPriority priority)12326 virtual void SetPriority(RequestPriority priority) OVERRIDE {
12327 priority_ = priority;
12328 }
12329
was_npn_negotiated() const12330 virtual bool was_npn_negotiated() const OVERRIDE {
12331 return false;
12332 }
12333
protocol_negotiated() const12334 virtual NextProto protocol_negotiated() const OVERRIDE {
12335 return kProtoUnknown;
12336 }
12337
using_spdy() const12338 virtual bool using_spdy() const OVERRIDE {
12339 return false;
12340 }
12341
12342 private:
12343 RequestPriority priority_;
12344 HttpStreamRequest::Delegate* const delegate_;
12345 WebSocketHandshakeStreamBase::CreateHelper* websocket_stream_create_helper_;
12346
12347 DISALLOW_COPY_AND_ASSIGN(FakeStreamRequest);
12348 };
12349
12350 // Fake HttpStreamFactory that vends FakeStreamRequests.
12351 class FakeStreamFactory : public HttpStreamFactory {
12352 public:
FakeStreamFactory()12353 FakeStreamFactory() {}
~FakeStreamFactory()12354 virtual ~FakeStreamFactory() {}
12355
12356 // Returns a WeakPtr<> to the last HttpStreamRequest returned by
12357 // RequestStream() (which may be NULL if it was destroyed already).
last_stream_request()12358 base::WeakPtr<FakeStreamRequest> last_stream_request() {
12359 return last_stream_request_;
12360 }
12361
RequestStream(const HttpRequestInfo & info,RequestPriority priority,const SSLConfig & server_ssl_config,const SSLConfig & proxy_ssl_config,HttpStreamRequest::Delegate * delegate,const BoundNetLog & net_log)12362 virtual HttpStreamRequest* RequestStream(
12363 const HttpRequestInfo& info,
12364 RequestPriority priority,
12365 const SSLConfig& server_ssl_config,
12366 const SSLConfig& proxy_ssl_config,
12367 HttpStreamRequest::Delegate* delegate,
12368 const BoundNetLog& net_log) OVERRIDE {
12369 FakeStreamRequest* fake_request = new FakeStreamRequest(priority, delegate);
12370 last_stream_request_ = fake_request->AsWeakPtr();
12371 return fake_request;
12372 }
12373
RequestWebSocketHandshakeStream(const HttpRequestInfo & info,RequestPriority priority,const SSLConfig & server_ssl_config,const SSLConfig & proxy_ssl_config,HttpStreamRequest::Delegate * delegate,WebSocketHandshakeStreamBase::CreateHelper * create_helper,const BoundNetLog & net_log)12374 virtual HttpStreamRequest* RequestWebSocketHandshakeStream(
12375 const HttpRequestInfo& info,
12376 RequestPriority priority,
12377 const SSLConfig& server_ssl_config,
12378 const SSLConfig& proxy_ssl_config,
12379 HttpStreamRequest::Delegate* delegate,
12380 WebSocketHandshakeStreamBase::CreateHelper* create_helper,
12381 const BoundNetLog& net_log) OVERRIDE {
12382 FakeStreamRequest* fake_request =
12383 new FakeStreamRequest(priority, delegate, create_helper);
12384 last_stream_request_ = fake_request->AsWeakPtr();
12385 return fake_request;
12386 }
12387
PreconnectStreams(int num_streams,const HttpRequestInfo & info,RequestPriority priority,const SSLConfig & server_ssl_config,const SSLConfig & proxy_ssl_config)12388 virtual void PreconnectStreams(int num_streams,
12389 const HttpRequestInfo& info,
12390 RequestPriority priority,
12391 const SSLConfig& server_ssl_config,
12392 const SSLConfig& proxy_ssl_config) OVERRIDE {
12393 ADD_FAILURE();
12394 }
12395
GetHostMappingRules() const12396 virtual const HostMappingRules* GetHostMappingRules() const OVERRIDE {
12397 ADD_FAILURE();
12398 return NULL;
12399 }
12400
12401 private:
12402 base::WeakPtr<FakeStreamRequest> last_stream_request_;
12403
12404 DISALLOW_COPY_AND_ASSIGN(FakeStreamFactory);
12405 };
12406
12407 // TODO(yhirano): Split this class out into a net/websockets file, if it is
12408 // worth doing.
12409 class FakeWebSocketStreamCreateHelper :
12410 public WebSocketHandshakeStreamBase::CreateHelper {
12411 public:
CreateBasicStream(scoped_ptr<ClientSocketHandle> connection,bool using_proxy)12412 virtual WebSocketHandshakeStreamBase* CreateBasicStream(
12413 scoped_ptr<ClientSocketHandle> connection,
12414 bool using_proxy) OVERRIDE {
12415 NOTREACHED();
12416 return NULL;
12417 }
12418
CreateSpdyStream(const base::WeakPtr<SpdySession> & session,bool use_relative_url)12419 virtual WebSocketHandshakeStreamBase* CreateSpdyStream(
12420 const base::WeakPtr<SpdySession>& session,
12421 bool use_relative_url) OVERRIDE {
12422 NOTREACHED();
12423 return NULL;
12424 };
12425
~FakeWebSocketStreamCreateHelper()12426 virtual ~FakeWebSocketStreamCreateHelper() {}
12427
Upgrade()12428 virtual scoped_ptr<WebSocketStream> Upgrade() {
12429 NOTREACHED();
12430 return scoped_ptr<WebSocketStream>();
12431 }
12432 };
12433
12434 } // namespace
12435
12436 // Make sure that HttpNetworkTransaction passes on its priority to its
12437 // stream request on start.
TEST_P(HttpNetworkTransactionTest,SetStreamRequestPriorityOnStart)12438 TEST_P(HttpNetworkTransactionTest, SetStreamRequestPriorityOnStart) {
12439 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12440 HttpNetworkSessionPeer peer(session);
12441 FakeStreamFactory* fake_factory = new FakeStreamFactory();
12442 peer.SetHttpStreamFactory(scoped_ptr<HttpStreamFactory>(fake_factory));
12443
12444 HttpNetworkTransaction trans(LOW, session);
12445
12446 ASSERT_TRUE(fake_factory->last_stream_request() == NULL);
12447
12448 HttpRequestInfo request;
12449 TestCompletionCallback callback;
12450 EXPECT_EQ(ERR_IO_PENDING,
12451 trans.Start(&request, callback.callback(), BoundNetLog()));
12452
12453 base::WeakPtr<FakeStreamRequest> fake_request =
12454 fake_factory->last_stream_request();
12455 ASSERT_TRUE(fake_request != NULL);
12456 EXPECT_EQ(LOW, fake_request->priority());
12457 }
12458
12459 // Make sure that HttpNetworkTransaction passes on its priority
12460 // updates to its stream request.
TEST_P(HttpNetworkTransactionTest,SetStreamRequestPriority)12461 TEST_P(HttpNetworkTransactionTest, SetStreamRequestPriority) {
12462 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12463 HttpNetworkSessionPeer peer(session);
12464 FakeStreamFactory* fake_factory = new FakeStreamFactory();
12465 peer.SetHttpStreamFactory(scoped_ptr<HttpStreamFactory>(fake_factory));
12466
12467 HttpNetworkTransaction trans(LOW, session);
12468
12469 HttpRequestInfo request;
12470 TestCompletionCallback callback;
12471 EXPECT_EQ(ERR_IO_PENDING,
12472 trans.Start(&request, callback.callback(), BoundNetLog()));
12473
12474 base::WeakPtr<FakeStreamRequest> fake_request =
12475 fake_factory->last_stream_request();
12476 ASSERT_TRUE(fake_request != NULL);
12477 EXPECT_EQ(LOW, fake_request->priority());
12478
12479 trans.SetPriority(LOWEST);
12480 ASSERT_TRUE(fake_request != NULL);
12481 EXPECT_EQ(LOWEST, fake_request->priority());
12482 }
12483
12484 // Make sure that HttpNetworkTransaction passes on its priority
12485 // updates to its stream.
TEST_P(HttpNetworkTransactionTest,SetStreamPriority)12486 TEST_P(HttpNetworkTransactionTest, SetStreamPriority) {
12487 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12488 HttpNetworkSessionPeer peer(session);
12489 FakeStreamFactory* fake_factory = new FakeStreamFactory();
12490 peer.SetHttpStreamFactory(scoped_ptr<HttpStreamFactory>(fake_factory));
12491
12492 HttpNetworkTransaction trans(LOW, session);
12493
12494 HttpRequestInfo request;
12495 TestCompletionCallback callback;
12496 EXPECT_EQ(ERR_IO_PENDING,
12497 trans.Start(&request, callback.callback(), BoundNetLog()));
12498
12499 base::WeakPtr<FakeStreamRequest> fake_request =
12500 fake_factory->last_stream_request();
12501 ASSERT_TRUE(fake_request != NULL);
12502 base::WeakPtr<FakeStream> fake_stream = fake_request->FinishStreamRequest();
12503 ASSERT_TRUE(fake_stream != NULL);
12504 EXPECT_EQ(LOW, fake_stream->priority());
12505
12506 trans.SetPriority(LOWEST);
12507 EXPECT_EQ(LOWEST, fake_stream->priority());
12508 }
12509
TEST_P(HttpNetworkTransactionTest,CreateWebSocketHandshakeStream)12510 TEST_P(HttpNetworkTransactionTest, CreateWebSocketHandshakeStream) {
12511 // The same logic needs to be tested for both ws: and wss: schemes, but this
12512 // test is already parameterised on NextProto, so it uses a loop to verify
12513 // that the different schemes work.
12514 std::string test_cases[] = {"ws://www.google.com/", "wss://www.google.com/"};
12515 for (size_t i = 0; i < arraysize(test_cases); ++i) {
12516 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12517 HttpNetworkSessionPeer peer(session);
12518 FakeStreamFactory* fake_factory = new FakeStreamFactory();
12519 FakeWebSocketStreamCreateHelper websocket_stream_create_helper;
12520 peer.SetHttpStreamFactoryForWebSocket(
12521 scoped_ptr<HttpStreamFactory>(fake_factory));
12522
12523 HttpNetworkTransaction trans(LOW, session);
12524 trans.SetWebSocketHandshakeStreamCreateHelper(
12525 &websocket_stream_create_helper);
12526
12527 HttpRequestInfo request;
12528 TestCompletionCallback callback;
12529 request.method = "GET";
12530 request.url = GURL(test_cases[i]);
12531
12532 EXPECT_EQ(ERR_IO_PENDING,
12533 trans.Start(&request, callback.callback(), BoundNetLog()));
12534
12535 base::WeakPtr<FakeStreamRequest> fake_request =
12536 fake_factory->last_stream_request();
12537 ASSERT_TRUE(fake_request != NULL);
12538 EXPECT_EQ(&websocket_stream_create_helper,
12539 fake_request->websocket_stream_create_helper());
12540 }
12541 }
12542
12543 // Tests that when a used socket is returned to the SSL socket pool, it's closed
12544 // if the transport socket pool is stalled on the global socket limit.
TEST_P(HttpNetworkTransactionTest,CloseSSLSocketOnIdleForHttpRequest)12545 TEST_P(HttpNetworkTransactionTest, CloseSSLSocketOnIdleForHttpRequest) {
12546 ClientSocketPoolManager::set_max_sockets_per_group(
12547 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
12548 ClientSocketPoolManager::set_max_sockets_per_pool(
12549 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
12550
12551 // Set up SSL request.
12552
12553 HttpRequestInfo ssl_request;
12554 ssl_request.method = "GET";
12555 ssl_request.url = GURL("https://www.google.com/");
12556
12557 MockWrite ssl_writes[] = {
12558 MockWrite("GET / HTTP/1.1\r\n"
12559 "Host: www.google.com\r\n"
12560 "Connection: keep-alive\r\n\r\n"),
12561 };
12562 MockRead ssl_reads[] = {
12563 MockRead("HTTP/1.1 200 OK\r\n"),
12564 MockRead("Content-Length: 11\r\n\r\n"),
12565 MockRead("hello world"),
12566 MockRead(SYNCHRONOUS, OK),
12567 };
12568 StaticSocketDataProvider ssl_data(ssl_reads, arraysize(ssl_reads),
12569 ssl_writes, arraysize(ssl_writes));
12570 session_deps_.socket_factory->AddSocketDataProvider(&ssl_data);
12571
12572 SSLSocketDataProvider ssl(ASYNC, OK);
12573 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12574
12575 // Set up HTTP request.
12576
12577 HttpRequestInfo http_request;
12578 http_request.method = "GET";
12579 http_request.url = GURL("http://www.google.com/");
12580
12581 MockWrite http_writes[] = {
12582 MockWrite("GET / HTTP/1.1\r\n"
12583 "Host: www.google.com\r\n"
12584 "Connection: keep-alive\r\n\r\n"),
12585 };
12586 MockRead http_reads[] = {
12587 MockRead("HTTP/1.1 200 OK\r\n"),
12588 MockRead("Content-Length: 7\r\n\r\n"),
12589 MockRead("falafel"),
12590 MockRead(SYNCHRONOUS, OK),
12591 };
12592 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
12593 http_writes, arraysize(http_writes));
12594 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
12595
12596 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12597
12598 // Start the SSL request.
12599 TestCompletionCallback ssl_callback;
12600 scoped_ptr<HttpTransaction> ssl_trans(
12601 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12602 ASSERT_EQ(ERR_IO_PENDING,
12603 ssl_trans->Start(&ssl_request, ssl_callback.callback(),
12604 BoundNetLog()));
12605
12606 // Start the HTTP request. Pool should stall.
12607 TestCompletionCallback http_callback;
12608 scoped_ptr<HttpTransaction> http_trans(
12609 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12610 ASSERT_EQ(ERR_IO_PENDING,
12611 http_trans->Start(&http_request, http_callback.callback(),
12612 BoundNetLog()));
12613 EXPECT_TRUE(IsTransportSocketPoolStalled(session));
12614
12615 // Wait for response from SSL request.
12616 ASSERT_EQ(OK, ssl_callback.WaitForResult());
12617 std::string response_data;
12618 ASSERT_EQ(OK, ReadTransaction(ssl_trans.get(), &response_data));
12619 EXPECT_EQ("hello world", response_data);
12620
12621 // The SSL socket should automatically be closed, so the HTTP request can
12622 // start.
12623 EXPECT_EQ(0, GetIdleSocketCountInSSLSocketPool(session));
12624 ASSERT_FALSE(IsTransportSocketPoolStalled(session));
12625
12626 // The HTTP request can now complete.
12627 ASSERT_EQ(OK, http_callback.WaitForResult());
12628 ASSERT_EQ(OK, ReadTransaction(http_trans.get(), &response_data));
12629 EXPECT_EQ("falafel", response_data);
12630
12631 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session));
12632 }
12633
12634 // Tests that when a SSL connection is established but there's no corresponding
12635 // request that needs it, the new socket is closed if the transport socket pool
12636 // is stalled on the global socket limit.
TEST_P(HttpNetworkTransactionTest,CloseSSLSocketOnIdleForHttpRequest2)12637 TEST_P(HttpNetworkTransactionTest, CloseSSLSocketOnIdleForHttpRequest2) {
12638 ClientSocketPoolManager::set_max_sockets_per_group(
12639 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
12640 ClientSocketPoolManager::set_max_sockets_per_pool(
12641 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
12642
12643 // Set up an ssl request.
12644
12645 HttpRequestInfo ssl_request;
12646 ssl_request.method = "GET";
12647 ssl_request.url = GURL("https://www.foopy.com/");
12648
12649 // No data will be sent on the SSL socket.
12650 StaticSocketDataProvider ssl_data;
12651 session_deps_.socket_factory->AddSocketDataProvider(&ssl_data);
12652
12653 SSLSocketDataProvider ssl(ASYNC, OK);
12654 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12655
12656 // Set up HTTP request.
12657
12658 HttpRequestInfo http_request;
12659 http_request.method = "GET";
12660 http_request.url = GURL("http://www.google.com/");
12661
12662 MockWrite http_writes[] = {
12663 MockWrite("GET / HTTP/1.1\r\n"
12664 "Host: www.google.com\r\n"
12665 "Connection: keep-alive\r\n\r\n"),
12666 };
12667 MockRead http_reads[] = {
12668 MockRead("HTTP/1.1 200 OK\r\n"),
12669 MockRead("Content-Length: 7\r\n\r\n"),
12670 MockRead("falafel"),
12671 MockRead(SYNCHRONOUS, OK),
12672 };
12673 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
12674 http_writes, arraysize(http_writes));
12675 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
12676
12677 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12678
12679 // Preconnect an SSL socket. A preconnect is needed because connect jobs are
12680 // cancelled when a normal transaction is cancelled.
12681 net::HttpStreamFactory* http_stream_factory = session->http_stream_factory();
12682 net::SSLConfig ssl_config;
12683 session->ssl_config_service()->GetSSLConfig(&ssl_config);
12684 http_stream_factory->PreconnectStreams(1, ssl_request, DEFAULT_PRIORITY,
12685 ssl_config, ssl_config);
12686 EXPECT_EQ(0, GetIdleSocketCountInSSLSocketPool(session));
12687
12688 // Start the HTTP request. Pool should stall.
12689 TestCompletionCallback http_callback;
12690 scoped_ptr<HttpTransaction> http_trans(
12691 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12692 ASSERT_EQ(ERR_IO_PENDING,
12693 http_trans->Start(&http_request, http_callback.callback(),
12694 BoundNetLog()));
12695 EXPECT_TRUE(IsTransportSocketPoolStalled(session));
12696
12697 // The SSL connection will automatically be closed once the connection is
12698 // established, to let the HTTP request start.
12699 ASSERT_EQ(OK, http_callback.WaitForResult());
12700 std::string response_data;
12701 ASSERT_EQ(OK, ReadTransaction(http_trans.get(), &response_data));
12702 EXPECT_EQ("falafel", response_data);
12703
12704 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session));
12705 }
12706
TEST_P(HttpNetworkTransactionTest,PostReadsErrorResponseAfterReset)12707 TEST_P(HttpNetworkTransactionTest, PostReadsErrorResponseAfterReset) {
12708 ScopedVector<UploadElementReader> element_readers;
12709 element_readers.push_back(new UploadBytesElementReader("foo", 3));
12710 UploadDataStream upload_data_stream(element_readers.Pass(), 0);
12711
12712 HttpRequestInfo request;
12713 request.method = "POST";
12714 request.url = GURL("http://www.foo.com/");
12715 request.upload_data_stream = &upload_data_stream;
12716 request.load_flags = 0;
12717
12718 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12719 scoped_ptr<HttpTransaction> trans(
12720 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
12721 // Send headers successfully, but get an error while sending the body.
12722 MockWrite data_writes[] = {
12723 MockWrite("POST / HTTP/1.1\r\n"
12724 "Host: www.foo.com\r\n"
12725 "Connection: keep-alive\r\n"
12726 "Content-Length: 3\r\n\r\n"),
12727 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
12728 };
12729
12730 MockRead data_reads[] = {
12731 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
12732 MockRead("hello world"),
12733 MockRead(SYNCHRONOUS, OK),
12734 };
12735 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
12736 arraysize(data_writes));
12737 session_deps_.socket_factory->AddSocketDataProvider(&data);
12738
12739 TestCompletionCallback callback;
12740
12741 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
12742 EXPECT_EQ(ERR_IO_PENDING, rv);
12743
12744 rv = callback.WaitForResult();
12745 EXPECT_EQ(OK, rv);
12746
12747 const HttpResponseInfo* response = trans->GetResponseInfo();
12748 ASSERT_TRUE(response != NULL);
12749
12750 EXPECT_TRUE(response->headers.get() != NULL);
12751 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
12752
12753 std::string response_data;
12754 rv = ReadTransaction(trans.get(), &response_data);
12755 EXPECT_EQ(OK, rv);
12756 EXPECT_EQ("hello world", response_data);
12757 }
12758
12759 // This test makes sure the retry logic doesn't trigger when reading an error
12760 // response from a server that rejected a POST with a CONNECTION_RESET.
TEST_P(HttpNetworkTransactionTest,PostReadsErrorResponseAfterResetOnReusedSocket)12761 TEST_P(HttpNetworkTransactionTest,
12762 PostReadsErrorResponseAfterResetOnReusedSocket) {
12763 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12764 MockWrite data_writes[] = {
12765 MockWrite("GET / HTTP/1.1\r\n"
12766 "Host: www.foo.com\r\n"
12767 "Connection: keep-alive\r\n\r\n"),
12768 MockWrite("POST / HTTP/1.1\r\n"
12769 "Host: www.foo.com\r\n"
12770 "Connection: keep-alive\r\n"
12771 "Content-Length: 3\r\n\r\n"),
12772 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
12773 };
12774
12775 MockRead data_reads[] = {
12776 MockRead("HTTP/1.1 200 Peachy\r\n"
12777 "Content-Length: 14\r\n\r\n"),
12778 MockRead("first response"),
12779 MockRead("HTTP/1.1 400 Not OK\r\n"
12780 "Content-Length: 15\r\n\r\n"),
12781 MockRead("second response"),
12782 MockRead(SYNCHRONOUS, OK),
12783 };
12784 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
12785 arraysize(data_writes));
12786 session_deps_.socket_factory->AddSocketDataProvider(&data);
12787
12788 TestCompletionCallback callback;
12789 HttpRequestInfo request1;
12790 request1.method = "GET";
12791 request1.url = GURL("http://www.foo.com/");
12792 request1.load_flags = 0;
12793
12794 scoped_ptr<HttpTransaction> trans1(
12795 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
12796 int rv = trans1->Start(&request1, callback.callback(), BoundNetLog());
12797 EXPECT_EQ(ERR_IO_PENDING, rv);
12798
12799 rv = callback.WaitForResult();
12800 EXPECT_EQ(OK, rv);
12801
12802 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
12803 ASSERT_TRUE(response1 != NULL);
12804
12805 EXPECT_TRUE(response1->headers.get() != NULL);
12806 EXPECT_EQ("HTTP/1.1 200 Peachy", response1->headers->GetStatusLine());
12807
12808 std::string response_data1;
12809 rv = ReadTransaction(trans1.get(), &response_data1);
12810 EXPECT_EQ(OK, rv);
12811 EXPECT_EQ("first response", response_data1);
12812 // Delete the transaction to release the socket back into the socket pool.
12813 trans1.reset();
12814
12815 ScopedVector<UploadElementReader> element_readers;
12816 element_readers.push_back(new UploadBytesElementReader("foo", 3));
12817 UploadDataStream upload_data_stream(element_readers.Pass(), 0);
12818
12819 HttpRequestInfo request2;
12820 request2.method = "POST";
12821 request2.url = GURL("http://www.foo.com/");
12822 request2.upload_data_stream = &upload_data_stream;
12823 request2.load_flags = 0;
12824
12825 scoped_ptr<HttpTransaction> trans2(
12826 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
12827 rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
12828 EXPECT_EQ(ERR_IO_PENDING, rv);
12829
12830 rv = callback.WaitForResult();
12831 EXPECT_EQ(OK, rv);
12832
12833 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
12834 ASSERT_TRUE(response2 != NULL);
12835
12836 EXPECT_TRUE(response2->headers.get() != NULL);
12837 EXPECT_EQ("HTTP/1.1 400 Not OK", response2->headers->GetStatusLine());
12838
12839 std::string response_data2;
12840 rv = ReadTransaction(trans2.get(), &response_data2);
12841 EXPECT_EQ(OK, rv);
12842 EXPECT_EQ("second response", response_data2);
12843 }
12844
TEST_P(HttpNetworkTransactionTest,PostReadsErrorResponseAfterResetPartialBodySent)12845 TEST_P(HttpNetworkTransactionTest,
12846 PostReadsErrorResponseAfterResetPartialBodySent) {
12847 ScopedVector<UploadElementReader> element_readers;
12848 element_readers.push_back(new UploadBytesElementReader("foo", 3));
12849 UploadDataStream upload_data_stream(element_readers.Pass(), 0);
12850
12851 HttpRequestInfo request;
12852 request.method = "POST";
12853 request.url = GURL("http://www.foo.com/");
12854 request.upload_data_stream = &upload_data_stream;
12855 request.load_flags = 0;
12856
12857 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12858 scoped_ptr<HttpTransaction> trans(
12859 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
12860 // Send headers successfully, but get an error while sending the body.
12861 MockWrite data_writes[] = {
12862 MockWrite("POST / HTTP/1.1\r\n"
12863 "Host: www.foo.com\r\n"
12864 "Connection: keep-alive\r\n"
12865 "Content-Length: 3\r\n\r\n"
12866 "fo"),
12867 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
12868 };
12869
12870 MockRead data_reads[] = {
12871 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
12872 MockRead("hello world"),
12873 MockRead(SYNCHRONOUS, OK),
12874 };
12875 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
12876 arraysize(data_writes));
12877 session_deps_.socket_factory->AddSocketDataProvider(&data);
12878
12879 TestCompletionCallback callback;
12880
12881 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
12882 EXPECT_EQ(ERR_IO_PENDING, rv);
12883
12884 rv = callback.WaitForResult();
12885 EXPECT_EQ(OK, rv);
12886
12887 const HttpResponseInfo* response = trans->GetResponseInfo();
12888 ASSERT_TRUE(response != NULL);
12889
12890 EXPECT_TRUE(response->headers.get() != NULL);
12891 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
12892
12893 std::string response_data;
12894 rv = ReadTransaction(trans.get(), &response_data);
12895 EXPECT_EQ(OK, rv);
12896 EXPECT_EQ("hello world", response_data);
12897 }
12898
12899 // This tests the more common case than the previous test, where headers and
12900 // body are not merged into a single request.
TEST_P(HttpNetworkTransactionTest,ChunkedPostReadsErrorResponseAfterReset)12901 TEST_P(HttpNetworkTransactionTest, ChunkedPostReadsErrorResponseAfterReset) {
12902 ScopedVector<UploadElementReader> element_readers;
12903 element_readers.push_back(new UploadBytesElementReader("foo", 3));
12904 UploadDataStream upload_data_stream(UploadDataStream::CHUNKED, 0);
12905
12906 HttpRequestInfo request;
12907 request.method = "POST";
12908 request.url = GURL("http://www.foo.com/");
12909 request.upload_data_stream = &upload_data_stream;
12910 request.load_flags = 0;
12911
12912 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12913 scoped_ptr<HttpTransaction> trans(
12914 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
12915 // Send headers successfully, but get an error while sending the body.
12916 MockWrite data_writes[] = {
12917 MockWrite("POST / HTTP/1.1\r\n"
12918 "Host: www.foo.com\r\n"
12919 "Connection: keep-alive\r\n"
12920 "Transfer-Encoding: chunked\r\n\r\n"),
12921 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
12922 };
12923
12924 MockRead data_reads[] = {
12925 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
12926 MockRead("hello world"),
12927 MockRead(SYNCHRONOUS, OK),
12928 };
12929 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
12930 arraysize(data_writes));
12931 session_deps_.socket_factory->AddSocketDataProvider(&data);
12932
12933 TestCompletionCallback callback;
12934
12935 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
12936 EXPECT_EQ(ERR_IO_PENDING, rv);
12937 // Make sure the headers are sent before adding a chunk. This ensures that
12938 // they can't be merged with the body in a single send. Not currently
12939 // necessary since a chunked body is never merged with headers, but this makes
12940 // the test more future proof.
12941 base::RunLoop().RunUntilIdle();
12942
12943 upload_data_stream.AppendChunk("last chunk", 10, true);
12944
12945 rv = callback.WaitForResult();
12946 EXPECT_EQ(OK, rv);
12947
12948 const HttpResponseInfo* response = trans->GetResponseInfo();
12949 ASSERT_TRUE(response != NULL);
12950
12951 EXPECT_TRUE(response->headers.get() != NULL);
12952 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
12953
12954 std::string response_data;
12955 rv = ReadTransaction(trans.get(), &response_data);
12956 EXPECT_EQ(OK, rv);
12957 EXPECT_EQ("hello world", response_data);
12958 }
12959
TEST_P(HttpNetworkTransactionTest,PostReadsErrorResponseAfterResetAnd100)12960 TEST_P(HttpNetworkTransactionTest, PostReadsErrorResponseAfterResetAnd100) {
12961 ScopedVector<UploadElementReader> element_readers;
12962 element_readers.push_back(new UploadBytesElementReader("foo", 3));
12963 UploadDataStream upload_data_stream(element_readers.Pass(), 0);
12964
12965 HttpRequestInfo request;
12966 request.method = "POST";
12967 request.url = GURL("http://www.foo.com/");
12968 request.upload_data_stream = &upload_data_stream;
12969 request.load_flags = 0;
12970
12971 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12972 scoped_ptr<HttpTransaction> trans(
12973 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
12974
12975 MockWrite data_writes[] = {
12976 MockWrite("POST / HTTP/1.1\r\n"
12977 "Host: www.foo.com\r\n"
12978 "Connection: keep-alive\r\n"
12979 "Content-Length: 3\r\n\r\n"),
12980 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
12981 };
12982
12983 MockRead data_reads[] = {
12984 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
12985 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
12986 MockRead("hello world"),
12987 MockRead(SYNCHRONOUS, OK),
12988 };
12989 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
12990 arraysize(data_writes));
12991 session_deps_.socket_factory->AddSocketDataProvider(&data);
12992
12993 TestCompletionCallback callback;
12994
12995 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
12996 EXPECT_EQ(ERR_IO_PENDING, rv);
12997
12998 rv = callback.WaitForResult();
12999 EXPECT_EQ(OK, rv);
13000
13001 const HttpResponseInfo* response = trans->GetResponseInfo();
13002 ASSERT_TRUE(response != NULL);
13003
13004 EXPECT_TRUE(response->headers.get() != NULL);
13005 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
13006
13007 std::string response_data;
13008 rv = ReadTransaction(trans.get(), &response_data);
13009 EXPECT_EQ(OK, rv);
13010 EXPECT_EQ("hello world", response_data);
13011 }
13012
TEST_P(HttpNetworkTransactionTest,PostIgnoresNonErrorResponseAfterReset)13013 TEST_P(HttpNetworkTransactionTest, PostIgnoresNonErrorResponseAfterReset) {
13014 ScopedVector<UploadElementReader> element_readers;
13015 element_readers.push_back(new UploadBytesElementReader("foo", 3));
13016 UploadDataStream upload_data_stream(element_readers.Pass(), 0);
13017
13018 HttpRequestInfo request;
13019 request.method = "POST";
13020 request.url = GURL("http://www.foo.com/");
13021 request.upload_data_stream = &upload_data_stream;
13022 request.load_flags = 0;
13023
13024 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13025 scoped_ptr<HttpTransaction> trans(
13026 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
13027 // Send headers successfully, but get an error while sending the body.
13028 MockWrite data_writes[] = {
13029 MockWrite("POST / HTTP/1.1\r\n"
13030 "Host: www.foo.com\r\n"
13031 "Connection: keep-alive\r\n"
13032 "Content-Length: 3\r\n\r\n"),
13033 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
13034 };
13035
13036 MockRead data_reads[] = {
13037 MockRead("HTTP/1.0 200 Just Dandy\r\n\r\n"),
13038 MockRead("hello world"),
13039 MockRead(SYNCHRONOUS, OK),
13040 };
13041 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
13042 arraysize(data_writes));
13043 session_deps_.socket_factory->AddSocketDataProvider(&data);
13044
13045 TestCompletionCallback callback;
13046
13047 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
13048 EXPECT_EQ(ERR_IO_PENDING, rv);
13049
13050 rv = callback.WaitForResult();
13051 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
13052
13053 const HttpResponseInfo* response = trans->GetResponseInfo();
13054 EXPECT_TRUE(response == NULL);
13055 }
13056
TEST_P(HttpNetworkTransactionTest,PostIgnoresNonErrorResponseAfterResetAnd100)13057 TEST_P(HttpNetworkTransactionTest,
13058 PostIgnoresNonErrorResponseAfterResetAnd100) {
13059 ScopedVector<UploadElementReader> element_readers;
13060 element_readers.push_back(new UploadBytesElementReader("foo", 3));
13061 UploadDataStream upload_data_stream(element_readers.Pass(), 0);
13062
13063 HttpRequestInfo request;
13064 request.method = "POST";
13065 request.url = GURL("http://www.foo.com/");
13066 request.upload_data_stream = &upload_data_stream;
13067 request.load_flags = 0;
13068
13069 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13070 scoped_ptr<HttpTransaction> trans(
13071 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
13072 // Send headers successfully, but get an error while sending the body.
13073 MockWrite data_writes[] = {
13074 MockWrite("POST / HTTP/1.1\r\n"
13075 "Host: www.foo.com\r\n"
13076 "Connection: keep-alive\r\n"
13077 "Content-Length: 3\r\n\r\n"),
13078 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
13079 };
13080
13081 MockRead data_reads[] = {
13082 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
13083 MockRead("HTTP/1.0 302 Redirect\r\n"),
13084 MockRead("Location: http://somewhere-else.com/\r\n"),
13085 MockRead("Content-Length: 0\r\n\r\n"),
13086 MockRead(SYNCHRONOUS, OK),
13087 };
13088 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
13089 arraysize(data_writes));
13090 session_deps_.socket_factory->AddSocketDataProvider(&data);
13091
13092 TestCompletionCallback callback;
13093
13094 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
13095 EXPECT_EQ(ERR_IO_PENDING, rv);
13096
13097 rv = callback.WaitForResult();
13098 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
13099
13100 const HttpResponseInfo* response = trans->GetResponseInfo();
13101 EXPECT_TRUE(response == NULL);
13102 }
13103
TEST_P(HttpNetworkTransactionTest,PostIgnoresHttp09ResponseAfterReset)13104 TEST_P(HttpNetworkTransactionTest, PostIgnoresHttp09ResponseAfterReset) {
13105 ScopedVector<UploadElementReader> element_readers;
13106 element_readers.push_back(new UploadBytesElementReader("foo", 3));
13107 UploadDataStream upload_data_stream(element_readers.Pass(), 0);
13108
13109 HttpRequestInfo request;
13110 request.method = "POST";
13111 request.url = GURL("http://www.foo.com/");
13112 request.upload_data_stream = &upload_data_stream;
13113 request.load_flags = 0;
13114
13115 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13116 scoped_ptr<HttpTransaction> trans(
13117 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
13118 // Send headers successfully, but get an error while sending the body.
13119 MockWrite data_writes[] = {
13120 MockWrite("POST / HTTP/1.1\r\n"
13121 "Host: www.foo.com\r\n"
13122 "Connection: keep-alive\r\n"
13123 "Content-Length: 3\r\n\r\n"),
13124 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
13125 };
13126
13127 MockRead data_reads[] = {
13128 MockRead("HTTP 0.9 rocks!"),
13129 MockRead(SYNCHRONOUS, OK),
13130 };
13131 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
13132 arraysize(data_writes));
13133 session_deps_.socket_factory->AddSocketDataProvider(&data);
13134
13135 TestCompletionCallback callback;
13136
13137 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
13138 EXPECT_EQ(ERR_IO_PENDING, rv);
13139
13140 rv = callback.WaitForResult();
13141 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
13142
13143 const HttpResponseInfo* response = trans->GetResponseInfo();
13144 EXPECT_TRUE(response == NULL);
13145 }
13146
TEST_P(HttpNetworkTransactionTest,PostIgnoresPartial400HeadersAfterReset)13147 TEST_P(HttpNetworkTransactionTest, PostIgnoresPartial400HeadersAfterReset) {
13148 ScopedVector<UploadElementReader> element_readers;
13149 element_readers.push_back(new UploadBytesElementReader("foo", 3));
13150 UploadDataStream upload_data_stream(element_readers.Pass(), 0);
13151
13152 HttpRequestInfo request;
13153 request.method = "POST";
13154 request.url = GURL("http://www.foo.com/");
13155 request.upload_data_stream = &upload_data_stream;
13156 request.load_flags = 0;
13157
13158 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13159 scoped_ptr<HttpTransaction> trans(
13160 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
13161 // Send headers successfully, but get an error while sending the body.
13162 MockWrite data_writes[] = {
13163 MockWrite("POST / HTTP/1.1\r\n"
13164 "Host: www.foo.com\r\n"
13165 "Connection: keep-alive\r\n"
13166 "Content-Length: 3\r\n\r\n"),
13167 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
13168 };
13169
13170 MockRead data_reads[] = {
13171 MockRead("HTTP/1.0 400 Not a Full Response\r\n"),
13172 MockRead(SYNCHRONOUS, OK),
13173 };
13174 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
13175 arraysize(data_writes));
13176 session_deps_.socket_factory->AddSocketDataProvider(&data);
13177
13178 TestCompletionCallback callback;
13179
13180 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
13181 EXPECT_EQ(ERR_IO_PENDING, rv);
13182
13183 rv = callback.WaitForResult();
13184 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
13185
13186 const HttpResponseInfo* response = trans->GetResponseInfo();
13187 EXPECT_TRUE(response == NULL);
13188 }
13189
13190 } // namespace net
13191