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
74using base::ASCIIToUTF16;
75
76//-----------------------------------------------------------------------------
77
78namespace {
79
80const base::string16 kBar(ASCIIToUTF16("bar"));
81const base::string16 kBar2(ASCIIToUTF16("bar2"));
82const base::string16 kBar3(ASCIIToUTF16("bar3"));
83const base::string16 kBaz(ASCIIToUTF16("baz"));
84const base::string16 kFirst(ASCIIToUTF16("first"));
85const base::string16 kFoo(ASCIIToUTF16("foo"));
86const base::string16 kFoo2(ASCIIToUTF16("foo2"));
87const base::string16 kFoo3(ASCIIToUTF16("foo3"));
88const base::string16 kFou(ASCIIToUTF16("fou"));
89const base::string16 kSecond(ASCIIToUTF16("second"));
90const base::string16 kTestingNTLM(ASCIIToUTF16("testing-ntlm"));
91const base::string16 kWrongPassword(ASCIIToUTF16("wrongpassword"));
92
93int GetIdleSocketCountInTransportSocketPool(net::HttpNetworkSession* session) {
94  return session->GetTransportSocketPool(
95      net::HttpNetworkSession::NORMAL_SOCKET_POOL)->IdleSocketCount();
96}
97
98int GetIdleSocketCountInSSLSocketPool(net::HttpNetworkSession* session) {
99  return session->GetSSLSocketPool(
100      net::HttpNetworkSession::NORMAL_SOCKET_POOL)->IdleSocketCount();
101}
102
103bool 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.
111bool 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.
125void 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.
145void 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.
168void 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.
189void 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
214namespace net {
215
216namespace {
217
218HttpNetworkSession* CreateSession(SpdySessionDependencies* session_deps) {
219  return SpdySessionDependencies::SpdyCreateSession(session_deps);
220}
221
222}  // namespace
223
224class HttpNetworkTransactionTest
225    : public PlatformTest,
226      public ::testing::WithParamInterface<NextProto> {
227 public:
228  virtual ~HttpNetworkTransactionTest() {
229    // Important to restore the per-pool limit first, since the pool limit must
230    // always be greater than group limit, and the tests reduce both limits.
231    ClientSocketPoolManager::set_max_sockets_per_pool(
232        HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_pool_sockets_);
233    ClientSocketPoolManager::set_max_sockets_per_group(
234        HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_group_sockets_);
235  }
236
237 protected:
238  HttpNetworkTransactionTest()
239      : spdy_util_(GetParam()),
240        session_deps_(GetParam()),
241        old_max_group_sockets_(ClientSocketPoolManager::max_sockets_per_group(
242            HttpNetworkSession::NORMAL_SOCKET_POOL)),
243        old_max_pool_sockets_(ClientSocketPoolManager::max_sockets_per_pool(
244            HttpNetworkSession::NORMAL_SOCKET_POOL)) {
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
255  virtual void SetUp() {
256    NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
257    base::MessageLoop::current()->RunUntilIdle();
258  }
259
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.
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
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
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
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
406INSTANTIATE_TEST_CASE_P(
407    NextProto,
408    HttpNetworkTransactionTest,
409    testing::Values(kProtoDeprecatedSPDY2,
410                    kProtoSPDY3, kProtoSPDY31, kProtoSPDY4));
411
412namespace {
413
414class BeforeNetworkStartHandler {
415 public:
416  explicit BeforeNetworkStartHandler(bool defer)
417      : defer_on_before_network_start_(defer),
418        observed_before_network_start_(false) {}
419
420  void OnBeforeNetworkStart(bool* defer) {
421    *defer = defer_on_before_network_start_;
422    observed_before_network_start_ = true;
423  }
424
425  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.
437void 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.
453void 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
464void 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
476std::string MockGetHostName() {
477  return "WTC-WIN7";
478}
479
480template<typename ParentPool>
481class CaptureGroupNameSocketPool : public ParentPool {
482 public:
483  CaptureGroupNameSocketPool(HostResolver* host_resolver,
484                             CertVerifier* cert_verifier);
485
486  const std::string last_group_name_received() const {
487    return last_group_name_;
488  }
489
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  }
499  virtual void CancelRequest(const std::string& group_name,
500                             ClientSocketHandle* handle) {}
501  virtual void ReleaseSocket(const std::string& group_name,
502                             scoped_ptr<StreamSocket> socket,
503                             int id) {}
504  virtual void CloseIdleSockets() {}
505  virtual int IdleSocketCount() const {
506    return 0;
507  }
508  virtual int IdleSocketCountInGroup(const std::string& group_name) const {
509    return 0;
510  }
511  virtual LoadState GetLoadState(const std::string& group_name,
512                                 const ClientSocketHandle* handle) const {
513    return LOAD_STATE_IDLE;
514  }
515  virtual base::TimeDelta ConnectionTimeout() const {
516    return base::TimeDelta();
517  }
518
519 private:
520  std::string last_group_name_;
521};
522
523typedef CaptureGroupNameSocketPool<TransportClientSocketPool>
524CaptureGroupNameTransportSocketPool;
525typedef CaptureGroupNameSocketPool<HttpProxyClientSocketPool>
526CaptureGroupNameHttpProxySocketPool;
527typedef CaptureGroupNameSocketPool<SOCKSClientSocketPool>
528CaptureGroupNameSOCKSSocketPool;
529typedef CaptureGroupNameSocketPool<SSLClientSocketPool>
530CaptureGroupNameSSLSocketPool;
531
532template<typename ParentPool>
533CaptureGroupNameSocketPool<ParentPool>::CaptureGroupNameSocketPool(
534    HostResolver* host_resolver,
535    CertVerifier* /* cert_verifier */)
536    : ParentPool(0, 0, NULL, host_resolver, NULL, NULL) {}
537
538template<>
539CaptureGroupNameHttpProxySocketPool::CaptureGroupNameSocketPool(
540    HostResolver* host_resolver,
541    CertVerifier* /* cert_verifier */)
542    : HttpProxyClientSocketPool(0, 0, NULL, host_resolver, NULL, NULL, NULL) {}
543
544template <>
545CaptureGroupNameSSLSocketPool::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.
568bool 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
578bool 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
588bool 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
598bool 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
610TEST_P(HttpNetworkTransactionTest, Basic) {
611  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
612  scoped_ptr<HttpTransaction> trans(
613      new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
614}
615
616TEST_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.
632TEST_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.
647TEST_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.
662TEST_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.
677TEST_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.
692TEST_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.
711TEST_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.
728TEST_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.
746TEST_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
771TEST_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
783TEST_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
798TEST_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
844TEST_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.
868TEST_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.
883TEST_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.
900TEST_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.
915TEST_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.
953TEST_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).
968TEST_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
1029TEST_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
1077TEST_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.
1124TEST_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
1163TEST_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
1194TEST_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
1220void 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
1309void 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
1429TEST_P(HttpNetworkTransactionTest,
1430       KeepAliveConnectionNotConnectedOnWrite) {
1431  MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
1432  KeepAliveConnectionResendRequestTest(&write_failure, NULL);
1433}
1434
1435TEST_P(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
1436  MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
1437  KeepAliveConnectionResendRequestTest(NULL, &read_failure);
1438}
1439
1440TEST_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.
1447TEST_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
1456TEST_P(HttpNetworkTransactionTest,
1457       PreconnectErrorNotConnectedOnWrite) {
1458  MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
1459  PreconnectErrorResendRequestTest(&write_failure, NULL, false);
1460}
1461
1462TEST_P(HttpNetworkTransactionTest, PreconnectErrorReset) {
1463  MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
1464  PreconnectErrorResendRequestTest(NULL, &read_failure, false);
1465}
1466
1467TEST_P(HttpNetworkTransactionTest, PreconnectErrorEOF) {
1468  MockRead read_failure(SYNCHRONOUS, OK);  // EOF
1469  PreconnectErrorResendRequestTest(NULL, &read_failure, false);
1470}
1471
1472TEST_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.
1479TEST_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
1489TEST_P(HttpNetworkTransactionTest,
1490       SpdyPreconnectErrorNotConnectedOnWrite) {
1491  MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
1492  PreconnectErrorResendRequestTest(&write_failure, NULL, true);
1493}
1494
1495TEST_P(HttpNetworkTransactionTest, SpdyPreconnectErrorReset) {
1496  MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
1497  PreconnectErrorResendRequestTest(NULL, &read_failure, true);
1498}
1499
1500TEST_P(HttpNetworkTransactionTest, SpdyPreconnectErrorEOF) {
1501  MockRead read_failure(SYNCHRONOUS, OK);  // EOF
1502  PreconnectErrorResendRequestTest(NULL, &read_failure, true);
1503}
1504
1505TEST_P(HttpNetworkTransactionTest, SpdyPreconnectErrorAsyncEOF) {
1506  MockRead read_failure(ASYNC, OK);  // EOF
1507  PreconnectErrorResendRequestTest(NULL, &read_failure, true);
1508}
1509
1510TEST_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)
1550TEST_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.
1563TEST_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.
1613TEST_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.
1645TEST_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
1686TEST_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.
1726TEST_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).
1835TEST_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
1936TEST_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.
1982TEST_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.
2082TEST_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.
2158TEST_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.
2242TEST_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.
2328TEST_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.
2444TEST_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.
2548TEST_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.
2607TEST_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.
2652TEST_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.
2711TEST_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.
2809TEST_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.
2908TEST_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.
2969TEST_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.
3034TEST_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.
3108TEST_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.
3211TEST_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.
3298TEST_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.
3387TEST_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.
3446TEST_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.
3597TEST_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.
3728TEST_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
3841TEST_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
3939void 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
3980void HttpNetworkTransactionTest::ConnectStatusHelper(
3981    const MockRead& status) {
3982  ConnectStatusHelperWithExpectedStatus(
3983      status, ERR_TUNNEL_CONNECTION_FAILED);
3984}
3985
3986TEST_P(HttpNetworkTransactionTest, ConnectStatus100) {
3987  ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
3988}
3989
3990TEST_P(HttpNetworkTransactionTest, ConnectStatus101) {
3991  ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
3992}
3993
3994TEST_P(HttpNetworkTransactionTest, ConnectStatus201) {
3995  ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
3996}
3997
3998TEST_P(HttpNetworkTransactionTest, ConnectStatus202) {
3999  ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
4000}
4001
4002TEST_P(HttpNetworkTransactionTest, ConnectStatus203) {
4003  ConnectStatusHelper(
4004      MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
4005}
4006
4007TEST_P(HttpNetworkTransactionTest, ConnectStatus204) {
4008  ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
4009}
4010
4011TEST_P(HttpNetworkTransactionTest, ConnectStatus205) {
4012  ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
4013}
4014
4015TEST_P(HttpNetworkTransactionTest, ConnectStatus206) {
4016  ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
4017}
4018
4019TEST_P(HttpNetworkTransactionTest, ConnectStatus300) {
4020  ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
4021}
4022
4023TEST_P(HttpNetworkTransactionTest, ConnectStatus301) {
4024  ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
4025}
4026
4027TEST_P(HttpNetworkTransactionTest, ConnectStatus302) {
4028  ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
4029}
4030
4031TEST_P(HttpNetworkTransactionTest, ConnectStatus303) {
4032  ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
4033}
4034
4035TEST_P(HttpNetworkTransactionTest, ConnectStatus304) {
4036  ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
4037}
4038
4039TEST_P(HttpNetworkTransactionTest, ConnectStatus305) {
4040  ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
4041}
4042
4043TEST_P(HttpNetworkTransactionTest, ConnectStatus306) {
4044  ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
4045}
4046
4047TEST_P(HttpNetworkTransactionTest, ConnectStatus307) {
4048  ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
4049}
4050
4051TEST_P(HttpNetworkTransactionTest, ConnectStatus308) {
4052  ConnectStatusHelper(MockRead("HTTP/1.1 308 Permanent Redirect\r\n"));
4053}
4054
4055TEST_P(HttpNetworkTransactionTest, ConnectStatus400) {
4056  ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
4057}
4058
4059TEST_P(HttpNetworkTransactionTest, ConnectStatus401) {
4060  ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
4061}
4062
4063TEST_P(HttpNetworkTransactionTest, ConnectStatus402) {
4064  ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
4065}
4066
4067TEST_P(HttpNetworkTransactionTest, ConnectStatus403) {
4068  ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
4069}
4070
4071TEST_P(HttpNetworkTransactionTest, ConnectStatus404) {
4072  ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
4073}
4074
4075TEST_P(HttpNetworkTransactionTest, ConnectStatus405) {
4076  ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
4077}
4078
4079TEST_P(HttpNetworkTransactionTest, ConnectStatus406) {
4080  ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
4081}
4082
4083TEST_P(HttpNetworkTransactionTest, ConnectStatus407) {
4084  ConnectStatusHelperWithExpectedStatus(
4085      MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4086      ERR_PROXY_AUTH_UNSUPPORTED);
4087}
4088
4089TEST_P(HttpNetworkTransactionTest, ConnectStatus408) {
4090  ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
4091}
4092
4093TEST_P(HttpNetworkTransactionTest, ConnectStatus409) {
4094  ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
4095}
4096
4097TEST_P(HttpNetworkTransactionTest, ConnectStatus410) {
4098  ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
4099}
4100
4101TEST_P(HttpNetworkTransactionTest, ConnectStatus411) {
4102  ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
4103}
4104
4105TEST_P(HttpNetworkTransactionTest, ConnectStatus412) {
4106  ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
4107}
4108
4109TEST_P(HttpNetworkTransactionTest, ConnectStatus413) {
4110  ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
4111}
4112
4113TEST_P(HttpNetworkTransactionTest, ConnectStatus414) {
4114  ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
4115}
4116
4117TEST_P(HttpNetworkTransactionTest, ConnectStatus415) {
4118  ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
4119}
4120
4121TEST_P(HttpNetworkTransactionTest, ConnectStatus416) {
4122  ConnectStatusHelper(
4123      MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
4124}
4125
4126TEST_P(HttpNetworkTransactionTest, ConnectStatus417) {
4127  ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
4128}
4129
4130TEST_P(HttpNetworkTransactionTest, ConnectStatus500) {
4131  ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
4132}
4133
4134TEST_P(HttpNetworkTransactionTest, ConnectStatus501) {
4135  ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
4136}
4137
4138TEST_P(HttpNetworkTransactionTest, ConnectStatus502) {
4139  ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
4140}
4141
4142TEST_P(HttpNetworkTransactionTest, ConnectStatus503) {
4143  ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
4144}
4145
4146TEST_P(HttpNetworkTransactionTest, ConnectStatus504) {
4147  ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
4148}
4149
4150TEST_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.
4157TEST_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.
4287TEST_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.
4419TEST_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.
4621TEST_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
4659TEST_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.
4719TEST_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.
4775TEST_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.
4834TEST_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
4929TEST_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
4984TEST_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.
5076TEST_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.
5154TEST_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.
5265TEST_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.
5342TEST_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.
5726TEST_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.
5860TEST_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
5903TEST_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
5959TEST_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
6038TEST_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
6102TEST_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
6178TEST_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.
6240TEST_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.
6286TEST_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.
6348TEST_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.
6497TEST_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.
6615TEST_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
6699TEST_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
6780TEST_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
6819TEST_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
6858TEST_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
6898TEST_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
6935TEST_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
6972TEST_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
7009TEST_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
7048TEST_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
7087TEST_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
7125TEST_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
7167TEST_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
7226TEST_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
7290TEST_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
7349TEST_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
7422TEST_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
7500namespace {
7501
7502// Tests that for connection endpoints the group names are correctly set.
7503
7504struct GroupNameTest {
7505  std::string proxy_server;
7506  std::string url;
7507  std::string expected_group_name;
7508  bool ssl;
7509};
7510
7511scoped_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
7525int 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
7544TEST_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
7612TEST_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
7678TEST_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
7752TEST_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.
7779void 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:
7842TEST_P(HttpNetworkTransactionTest, BypassHostCacheOnRefresh1) {
7843  BypassHostCacheOnRefreshHelper(LOAD_BYPASS_CACHE);
7844}
7845
7846TEST_P(HttpNetworkTransactionTest, BypassHostCacheOnRefresh2) {
7847  BypassHostCacheOnRefreshHelper(LOAD_VALIDATE_CACHE);
7848}
7849
7850TEST_P(HttpNetworkTransactionTest, BypassHostCacheOnRefresh3) {
7851  BypassHostCacheOnRefreshHelper(LOAD_DISABLE_CACHE);
7852}
7853
7854// Make sure we can handle an error when writing the request.
7855TEST_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.
7882TEST_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.
7922TEST_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.
8000TEST_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
8034TEST_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
8070TEST_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
8126TEST_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
8171TEST_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.
8228TEST_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
8380TEST_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
8440TEST_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
8499TEST_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
8548TEST_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
8598TEST_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
8647TEST_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
8695TEST_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
8743TEST_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
8797TEST_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
8887TEST_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
9004TEST_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
9079class CapturingProxyResolver : public ProxyResolver {
9080 public:
9081  CapturingProxyResolver() : ProxyResolver(false /* expects_pac_bytes */) {}
9082  virtual ~CapturingProxyResolver() {}
9083
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
9096  virtual void CancelRequest(RequestHandle request) OVERRIDE {
9097    NOTREACHED();
9098  }
9099
9100  virtual LoadState GetLoadState(RequestHandle request) const OVERRIDE {
9101    NOTREACHED();
9102    return LOAD_STATE_IDLE;
9103  }
9104
9105  virtual void CancelSetPacScript() OVERRIDE {
9106    NOTREACHED();
9107  }
9108
9109  virtual int SetPacScript(const scoped_refptr<ProxyResolverScriptData>&,
9110                           const CompletionCallback& /*callback*/) OVERRIDE {
9111    return OK;
9112  }
9113
9114  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
9122TEST_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
9244TEST_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.
9350TEST_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
9747TEST_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.
9936TEST_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
9998TEST_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.
10042class UrlRecordingHttpAuthHandlerMock : public HttpAuthHandlerMock {
10043 public:
10044  explicit UrlRecordingHttpAuthHandlerMock(GURL* url) : url_(url) {}
10045
10046  virtual ~UrlRecordingHttpAuthHandlerMock() {}
10047
10048 protected:
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
10062TEST_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.
10223TEST_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
10266TEST_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.
10311TEST_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.
10368TEST_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.
10444TEST_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.
10499TEST_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.
10550void 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
10577TEST_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.
10596TEST_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.
10706TEST_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.
10829TEST_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
10938WRAPPED_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
11041TEST_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
11129class OneTimeCachingHostResolver : public net::HostResolver {
11130 public:
11131  explicit OneTimeCachingHostResolver(const HostPortPair& host_port)
11132      : host_port_(host_port) {}
11133  virtual ~OneTimeCachingHostResolver() {}
11134
11135  RuleBasedHostResolverProc* rules() { return host_resolver_.rules(); }
11136
11137  // HostResolver methods:
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
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
11157  virtual void CancelRequest(RequestHandle req) OVERRIDE {
11158    host_resolver_.CancelRequest(req);
11159  }
11160
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
11178WRAPPED_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
11290TEST_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
11371TEST_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
11485TEST_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
11557TEST_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
11686TEST_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
11760TEST_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
11926TEST_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
11956TEST_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
11986TEST_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
12022TEST_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
12058TEST_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
12096TEST_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
12134TEST_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
12177namespace {
12178
12179// Fake HttpStreamBase that simply records calls to SetPriority().
12180class FakeStream : public HttpStreamBase,
12181                   public base::SupportsWeakPtr<FakeStream> {
12182 public:
12183  explicit FakeStream(RequestPriority priority) : priority_(priority) {}
12184  virtual ~FakeStream() {}
12185
12186  RequestPriority priority() const { return priority_; }
12187
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
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
12202  virtual int ReadResponseHeaders(const CompletionCallback& callback) OVERRIDE {
12203    ADD_FAILURE();
12204    return ERR_UNEXPECTED;
12205  }
12206
12207  virtual int ReadResponseBody(IOBuffer* buf, int buf_len,
12208                               const CompletionCallback& callback) OVERRIDE {
12209    ADD_FAILURE();
12210    return ERR_UNEXPECTED;
12211  }
12212
12213  virtual void Close(bool not_reusable) OVERRIDE {}
12214
12215  virtual bool IsResponseBodyComplete() const OVERRIDE {
12216    ADD_FAILURE();
12217    return false;
12218  }
12219
12220  virtual bool CanFindEndOfResponse() const OVERRIDE {
12221    return false;
12222  }
12223
12224  virtual bool IsConnectionReused() const OVERRIDE {
12225    ADD_FAILURE();
12226    return false;
12227  }
12228
12229  virtual void SetConnectionReused() OVERRIDE {
12230    ADD_FAILURE();
12231  }
12232
12233  virtual bool IsConnectionReusable() const OVERRIDE {
12234    ADD_FAILURE();
12235    return false;
12236  }
12237
12238  virtual int64 GetTotalReceivedBytes() const OVERRIDE {
12239    ADD_FAILURE();
12240    return 0;
12241  }
12242
12243  virtual bool GetLoadTimingInfo(
12244      LoadTimingInfo* load_timing_info) const OVERRIDE {
12245    ADD_FAILURE();
12246    return false;
12247  }
12248
12249  virtual void GetSSLInfo(SSLInfo* ssl_info) OVERRIDE {
12250    ADD_FAILURE();
12251  }
12252
12253  virtual void GetSSLCertRequestInfo(
12254      SSLCertRequestInfo* cert_request_info) OVERRIDE {
12255    ADD_FAILURE();
12256  }
12257
12258  virtual bool IsSpdyHttpStream() const OVERRIDE {
12259    ADD_FAILURE();
12260    return false;
12261  }
12262
12263  virtual void Drain(HttpNetworkSession* session) OVERRIDE {
12264    ADD_FAILURE();
12265  }
12266
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.
12279class FakeStreamRequest : public HttpStreamRequest,
12280                          public base::SupportsWeakPtr<FakeStreamRequest> {
12281 public:
12282  FakeStreamRequest(RequestPriority priority,
12283                    HttpStreamRequest::Delegate* delegate)
12284      : priority_(priority),
12285        delegate_(delegate),
12286        websocket_stream_create_helper_(NULL) {}
12287
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
12295  virtual ~FakeStreamRequest() {}
12296
12297  RequestPriority priority() const { return priority_; }
12298
12299  const WebSocketHandshakeStreamBase::CreateHelper*
12300  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.
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
12315  virtual int RestartTunnelWithProxyAuth(
12316      const AuthCredentials& credentials) OVERRIDE {
12317    ADD_FAILURE();
12318    return ERR_UNEXPECTED;
12319  }
12320
12321  virtual LoadState GetLoadState() const OVERRIDE {
12322    ADD_FAILURE();
12323    return LoadState();
12324  }
12325
12326  virtual void SetPriority(RequestPriority priority) OVERRIDE {
12327    priority_ = priority;
12328  }
12329
12330  virtual bool was_npn_negotiated() const OVERRIDE {
12331    return false;
12332  }
12333
12334  virtual NextProto protocol_negotiated() const OVERRIDE {
12335    return kProtoUnknown;
12336  }
12337
12338  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.
12351class FakeStreamFactory : public HttpStreamFactory {
12352 public:
12353  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).
12358  base::WeakPtr<FakeStreamRequest> last_stream_request() {
12359    return last_stream_request_;
12360  }
12361
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
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
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
12396  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.
12409class FakeWebSocketStreamCreateHelper :
12410      public WebSocketHandshakeStreamBase::CreateHelper {
12411 public:
12412  virtual WebSocketHandshakeStreamBase* CreateBasicStream(
12413      scoped_ptr<ClientSocketHandle> connection,
12414      bool using_proxy) OVERRIDE {
12415    NOTREACHED();
12416    return NULL;
12417  }
12418
12419  virtual WebSocketHandshakeStreamBase* CreateSpdyStream(
12420      const base::WeakPtr<SpdySession>& session,
12421      bool use_relative_url) OVERRIDE {
12422    NOTREACHED();
12423    return NULL;
12424  };
12425
12426  virtual ~FakeWebSocketStreamCreateHelper() {}
12427
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.
12438TEST_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.
12461TEST_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.
12486TEST_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
12510TEST_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.
12545TEST_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.
12637TEST_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
12707TEST_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.
12761TEST_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
12845TEST_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.
12901TEST_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
12960TEST_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
13013TEST_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
13057TEST_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
13104TEST_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
13147TEST_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