http_network_transaction_unittest.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
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/strings/string_util.h"
20#include "base/strings/utf_string_conversions.h"
21#include "base/test/test_file_util.h"
22#include "net/base/auth.h"
23#include "net/base/capturing_net_log.h"
24#include "net/base/completion_callback.h"
25#include "net/base/load_timing_info.h"
26#include "net/base/load_timing_info_test_util.h"
27#include "net/base/net_log.h"
28#include "net/base/net_log_unittest.h"
29#include "net/base/request_priority.h"
30#include "net/base/test_completion_callback.h"
31#include "net/base/test_data_directory.h"
32#include "net/base/upload_bytes_element_reader.h"
33#include "net/base/upload_data_stream.h"
34#include "net/base/upload_file_element_reader.h"
35#include "net/cert/mock_cert_verifier.h"
36#include "net/dns/host_cache.h"
37#include "net/dns/mock_host_resolver.h"
38#include "net/http/http_auth_handler_digest.h"
39#include "net/http/http_auth_handler_mock.h"
40#include "net/http/http_auth_handler_ntlm.h"
41#include "net/http/http_basic_stream.h"
42#include "net/http/http_network_session.h"
43#include "net/http/http_network_session_peer.h"
44#include "net/http/http_server_properties_impl.h"
45#include "net/http/http_stream.h"
46#include "net/http/http_stream_factory.h"
47#include "net/http/http_transaction_unittest.h"
48#include "net/proxy/proxy_config_service_fixed.h"
49#include "net/proxy/proxy_info.h"
50#include "net/proxy/proxy_resolver.h"
51#include "net/proxy/proxy_service.h"
52#include "net/socket/client_socket_factory.h"
53#include "net/socket/client_socket_pool_manager.h"
54#include "net/socket/mock_client_socket_pool_manager.h"
55#include "net/socket/next_proto.h"
56#include "net/socket/socket_test_util.h"
57#include "net/socket/ssl_client_socket.h"
58#include "net/spdy/spdy_framer.h"
59#include "net/spdy/spdy_session.h"
60#include "net/spdy/spdy_session_pool.h"
61#include "net/spdy/spdy_test_util_common.h"
62#include "net/ssl/ssl_cert_request_info.h"
63#include "net/ssl/ssl_config_service.h"
64#include "net/ssl/ssl_config_service_defaults.h"
65#include "net/ssl/ssl_info.h"
66#include "net/test/cert_test_util.h"
67#include "net/websockets/websocket_handshake_stream_base.h"
68#include "testing/gtest/include/gtest/gtest.h"
69#include "testing/platform_test.h"
70#include "url/gurl.h"
71
72using base::ASCIIToUTF16;
73
74//-----------------------------------------------------------------------------
75
76namespace {
77
78const base::string16 kBar(ASCIIToUTF16("bar"));
79const base::string16 kBar2(ASCIIToUTF16("bar2"));
80const base::string16 kBar3(ASCIIToUTF16("bar3"));
81const base::string16 kBaz(ASCIIToUTF16("baz"));
82const base::string16 kFirst(ASCIIToUTF16("first"));
83const base::string16 kFoo(ASCIIToUTF16("foo"));
84const base::string16 kFoo2(ASCIIToUTF16("foo2"));
85const base::string16 kFoo3(ASCIIToUTF16("foo3"));
86const base::string16 kFou(ASCIIToUTF16("fou"));
87const base::string16 kSecond(ASCIIToUTF16("second"));
88const base::string16 kTestingNTLM(ASCIIToUTF16("testing-ntlm"));
89const base::string16 kWrongPassword(ASCIIToUTF16("wrongpassword"));
90
91int GetIdleSocketCountInTransportSocketPool(net::HttpNetworkSession* session) {
92  return session->GetTransportSocketPool(
93      net::HttpNetworkSession::NORMAL_SOCKET_POOL)->IdleSocketCount();
94}
95
96int GetIdleSocketCountInSSLSocketPool(net::HttpNetworkSession* session) {
97  return session->GetSSLSocketPool(
98      net::HttpNetworkSession::NORMAL_SOCKET_POOL)->IdleSocketCount();
99}
100
101bool IsTransportSocketPoolStalled(net::HttpNetworkSession* session) {
102  return session->GetTransportSocketPool(
103      net::HttpNetworkSession::NORMAL_SOCKET_POOL)->IsStalled();
104}
105
106// Takes in a Value created from a NetLogHttpResponseParameter, and returns
107// a JSONified list of headers as a single string.  Uses single quotes instead
108// of double quotes for easier comparison.  Returns false on failure.
109bool GetHeaders(base::DictionaryValue* params, std::string* headers) {
110  if (!params)
111    return false;
112  base::ListValue* header_list;
113  if (!params->GetList("headers", &header_list))
114    return false;
115  std::string double_quote_headers;
116  base::JSONWriter::Write(header_list, &double_quote_headers);
117  base::ReplaceChars(double_quote_headers, "\"", "'", headers);
118  return true;
119}
120
121// Tests LoadTimingInfo in the case a socket is reused and no PAC script is
122// used.
123void TestLoadTimingReused(const net::LoadTimingInfo& load_timing_info) {
124  EXPECT_TRUE(load_timing_info.socket_reused);
125  EXPECT_NE(net::NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
126
127  EXPECT_TRUE(load_timing_info.proxy_resolve_start.is_null());
128  EXPECT_TRUE(load_timing_info.proxy_resolve_end.is_null());
129
130  net::ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
131  EXPECT_FALSE(load_timing_info.send_start.is_null());
132
133  EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
134
135  // Set at a higher level.
136  EXPECT_TRUE(load_timing_info.request_start_time.is_null());
137  EXPECT_TRUE(load_timing_info.request_start.is_null());
138  EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
139}
140
141// Tests LoadTimingInfo in the case a new socket is used and no PAC script is
142// used.
143void TestLoadTimingNotReused(const net::LoadTimingInfo& load_timing_info,
144                             int connect_timing_flags) {
145  EXPECT_FALSE(load_timing_info.socket_reused);
146  EXPECT_NE(net::NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
147
148  EXPECT_TRUE(load_timing_info.proxy_resolve_start.is_null());
149  EXPECT_TRUE(load_timing_info.proxy_resolve_end.is_null());
150
151  net::ExpectConnectTimingHasTimes(load_timing_info.connect_timing,
152                                   connect_timing_flags);
153  EXPECT_LE(load_timing_info.connect_timing.connect_end,
154            load_timing_info.send_start);
155
156  EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
157
158  // Set at a higher level.
159  EXPECT_TRUE(load_timing_info.request_start_time.is_null());
160  EXPECT_TRUE(load_timing_info.request_start.is_null());
161  EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
162}
163
164// Tests LoadTimingInfo in the case a socket is reused and a PAC script is
165// used.
166void TestLoadTimingReusedWithPac(const net::LoadTimingInfo& load_timing_info) {
167  EXPECT_TRUE(load_timing_info.socket_reused);
168  EXPECT_NE(net::NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
169
170  net::ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
171
172  EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null());
173  EXPECT_LE(load_timing_info.proxy_resolve_start,
174            load_timing_info.proxy_resolve_end);
175  EXPECT_LE(load_timing_info.proxy_resolve_end,
176            load_timing_info.send_start);
177  EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
178
179  // Set at a higher level.
180  EXPECT_TRUE(load_timing_info.request_start_time.is_null());
181  EXPECT_TRUE(load_timing_info.request_start.is_null());
182  EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
183}
184
185// Tests LoadTimingInfo in the case a new socket is used and a PAC script is
186// used.
187void TestLoadTimingNotReusedWithPac(const net::LoadTimingInfo& load_timing_info,
188                                    int connect_timing_flags) {
189  EXPECT_FALSE(load_timing_info.socket_reused);
190  EXPECT_NE(net::NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
191
192  EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null());
193  EXPECT_LE(load_timing_info.proxy_resolve_start,
194            load_timing_info.proxy_resolve_end);
195  EXPECT_LE(load_timing_info.proxy_resolve_end,
196            load_timing_info.connect_timing.connect_start);
197  net::ExpectConnectTimingHasTimes(load_timing_info.connect_timing,
198                                   connect_timing_flags);
199  EXPECT_LE(load_timing_info.connect_timing.connect_end,
200            load_timing_info.send_start);
201
202  EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
203
204  // Set at a higher level.
205  EXPECT_TRUE(load_timing_info.request_start_time.is_null());
206  EXPECT_TRUE(load_timing_info.request_start.is_null());
207  EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
208}
209
210}  // namespace
211
212namespace net {
213
214namespace {
215
216HttpNetworkSession* CreateSession(SpdySessionDependencies* session_deps) {
217  return SpdySessionDependencies::SpdyCreateSession(session_deps);
218}
219
220}  // namespace
221
222class HttpNetworkTransactionTest
223    : public PlatformTest,
224      public ::testing::WithParamInterface<NextProto> {
225 public:
226  virtual ~HttpNetworkTransactionTest() {
227    // Important to restore the per-pool limit first, since the pool limit must
228    // always be greater than group limit, and the tests reduce both limits.
229    ClientSocketPoolManager::set_max_sockets_per_pool(
230        HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_pool_sockets_);
231    ClientSocketPoolManager::set_max_sockets_per_group(
232        HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_group_sockets_);
233  }
234
235 protected:
236  HttpNetworkTransactionTest()
237      : spdy_util_(GetParam()),
238        session_deps_(GetParam()),
239        old_max_group_sockets_(ClientSocketPoolManager::max_sockets_per_group(
240            HttpNetworkSession::NORMAL_SOCKET_POOL)),
241        old_max_pool_sockets_(ClientSocketPoolManager::max_sockets_per_pool(
242            HttpNetworkSession::NORMAL_SOCKET_POOL)) {
243  }
244
245  struct SimpleGetHelperResult {
246    int rv;
247    std::string status_line;
248    std::string response_data;
249    int64 totalReceivedBytes;
250    LoadTimingInfo load_timing_info;
251  };
252
253  virtual void SetUp() {
254    NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
255    base::MessageLoop::current()->RunUntilIdle();
256  }
257
258  virtual void TearDown() {
259    NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
260    base::MessageLoop::current()->RunUntilIdle();
261    // Empty the current queue.
262    base::MessageLoop::current()->RunUntilIdle();
263    PlatformTest::TearDown();
264    NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
265    base::MessageLoop::current()->RunUntilIdle();
266    HttpStreamFactory::set_use_alternate_protocols(false);
267    HttpStreamFactory::SetNextProtos(std::vector<NextProto>());
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  SimpleGetHelperResult SimpleGetHelperForData(StaticSocketDataProvider* data[],
286                                               size_t data_count) {
287    SimpleGetHelperResult out;
288
289    HttpRequestInfo request;
290    request.method = "GET";
291    request.url = GURL("http://www.google.com/");
292    request.load_flags = 0;
293
294    CapturingBoundNetLog log;
295    session_deps_.net_log = log.bound().net_log();
296    scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
297    scoped_ptr<HttpTransaction> trans(
298        new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
299
300    for (size_t i = 0; i < data_count; ++i) {
301      session_deps_.socket_factory->AddSocketDataProvider(data[i]);
302    }
303
304    TestCompletionCallback callback;
305
306    EXPECT_TRUE(log.bound().IsLoggingAllEvents());
307    int rv = trans->Start(&request, callback.callback(), log.bound());
308    EXPECT_EQ(ERR_IO_PENDING, rv);
309
310    out.rv = callback.WaitForResult();
311
312    // Even in the failure cases that use this function, connections are always
313    // successfully established before the error.
314    EXPECT_TRUE(trans->GetLoadTimingInfo(&out.load_timing_info));
315    TestLoadTimingNotReused(out.load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
316
317    if (out.rv != OK)
318      return out;
319
320    const HttpResponseInfo* response = trans->GetResponseInfo();
321    // Can't use ASSERT_* inside helper functions like this, so
322    // return an error.
323    if (response == NULL || response->headers.get() == NULL) {
324      out.rv = ERR_UNEXPECTED;
325      return out;
326    }
327    out.status_line = response->headers->GetStatusLine();
328
329    EXPECT_EQ("127.0.0.1", response->socket_address.host());
330    EXPECT_EQ(80, response->socket_address.port());
331
332    rv = ReadTransaction(trans.get(), &out.response_data);
333    EXPECT_EQ(OK, rv);
334
335    net::CapturingNetLog::CapturedEntryList entries;
336    log.GetEntries(&entries);
337    size_t pos = ExpectLogContainsSomewhere(
338        entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS,
339        NetLog::PHASE_NONE);
340    ExpectLogContainsSomewhere(
341        entries, pos,
342        NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS,
343        NetLog::PHASE_NONE);
344
345    std::string line;
346    EXPECT_TRUE(entries[pos].GetStringValue("line", &line));
347    EXPECT_EQ("GET / HTTP/1.1\r\n", line);
348
349    HttpRequestHeaders request_headers;
350    EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
351    std::string value;
352    EXPECT_TRUE(request_headers.GetHeader("Host", &value));
353    EXPECT_EQ("www.google.com", value);
354    EXPECT_TRUE(request_headers.GetHeader("Connection", &value));
355    EXPECT_EQ("keep-alive", value);
356
357    std::string response_headers;
358    EXPECT_TRUE(GetHeaders(entries[pos].params.get(), &response_headers));
359    EXPECT_EQ("['Host: www.google.com','Connection: keep-alive']",
360              response_headers);
361
362    out.totalReceivedBytes = trans->GetTotalReceivedBytes();
363    return out;
364  }
365
366  SimpleGetHelperResult SimpleGetHelper(MockRead data_reads[],
367                                        size_t reads_count) {
368    StaticSocketDataProvider reads(data_reads, reads_count, NULL, 0);
369    StaticSocketDataProvider* data[] = { &reads };
370    return SimpleGetHelperForData(data, 1);
371  }
372
373  int64 ReadsSize(MockRead data_reads[], size_t reads_count) {
374    int64 size = 0;
375    for (size_t i = 0; i < reads_count; ++i)
376      size += data_reads[i].data_len;
377    return size;
378  }
379
380  void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
381                                             int expected_status);
382
383  void ConnectStatusHelper(const MockRead& status);
384
385  void BypassHostCacheOnRefreshHelper(int load_flags);
386
387  void CheckErrorIsPassedBack(int error, IoMode mode);
388
389  SpdyTestUtil spdy_util_;
390  SpdySessionDependencies session_deps_;
391
392  // Original socket limits.  Some tests set these.  Safest to always restore
393  // them once each test has been run.
394  int old_max_group_sockets_;
395  int old_max_pool_sockets_;
396};
397
398INSTANTIATE_TEST_CASE_P(
399    NextProto,
400    HttpNetworkTransactionTest,
401    testing::Values(kProtoDeprecatedSPDY2,
402                    kProtoSPDY3, kProtoSPDY31, kProtoSPDY4a2,
403                    kProtoHTTP2Draft04));
404
405namespace {
406
407class BeforeNetworkStartHandler {
408 public:
409  explicit BeforeNetworkStartHandler(bool defer)
410      : defer_on_before_network_start_(defer),
411        observed_before_network_start_(false) {}
412
413  void OnBeforeNetworkStart(bool* defer) {
414    *defer = defer_on_before_network_start_;
415    observed_before_network_start_ = true;
416  }
417
418  bool observed_before_network_start() const {
419    return observed_before_network_start_;
420  }
421
422 private:
423  const bool defer_on_before_network_start_;
424  bool observed_before_network_start_;
425
426  DISALLOW_COPY_AND_ASSIGN(BeforeNetworkStartHandler);
427};
428
429// Fill |str| with a long header list that consumes >= |size| bytes.
430void FillLargeHeadersString(std::string* str, int size) {
431  const char* row =
432      "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
433  const int sizeof_row = strlen(row);
434  const int num_rows = static_cast<int>(
435      ceil(static_cast<float>(size) / sizeof_row));
436  const int sizeof_data = num_rows * sizeof_row;
437  DCHECK(sizeof_data >= size);
438  str->reserve(sizeof_data);
439
440  for (int i = 0; i < num_rows; ++i)
441    str->append(row, sizeof_row);
442}
443
444// Alternative functions that eliminate randomness and dependency on the local
445// host name so that the generated NTLM messages are reproducible.
446void MockGenerateRandom1(uint8* output, size_t n) {
447  static const uint8 bytes[] = {
448    0x55, 0x29, 0x66, 0x26, 0x6b, 0x9c, 0x73, 0x54
449  };
450  static size_t current_byte = 0;
451  for (size_t i = 0; i < n; ++i) {
452    output[i] = bytes[current_byte++];
453    current_byte %= arraysize(bytes);
454  }
455}
456
457void MockGenerateRandom2(uint8* output, size_t n) {
458  static const uint8 bytes[] = {
459    0x96, 0x79, 0x85, 0xe7, 0x49, 0x93, 0x70, 0xa1,
460    0x4e, 0xe7, 0x87, 0x45, 0x31, 0x5b, 0xd3, 0x1f
461  };
462  static size_t current_byte = 0;
463  for (size_t i = 0; i < n; ++i) {
464    output[i] = bytes[current_byte++];
465    current_byte %= arraysize(bytes);
466  }
467}
468
469std::string MockGetHostName() {
470  return "WTC-WIN7";
471}
472
473template<typename ParentPool>
474class CaptureGroupNameSocketPool : public ParentPool {
475 public:
476  CaptureGroupNameSocketPool(HostResolver* host_resolver,
477                             CertVerifier* cert_verifier);
478
479  const std::string last_group_name_received() const {
480    return last_group_name_;
481  }
482
483  virtual int RequestSocket(const std::string& group_name,
484                            const void* socket_params,
485                            RequestPriority priority,
486                            ClientSocketHandle* handle,
487                            const CompletionCallback& callback,
488                            const BoundNetLog& net_log) {
489    last_group_name_ = group_name;
490    return ERR_IO_PENDING;
491  }
492  virtual void CancelRequest(const std::string& group_name,
493                             ClientSocketHandle* handle) {}
494  virtual void ReleaseSocket(const std::string& group_name,
495                             scoped_ptr<StreamSocket> socket,
496                             int id) {}
497  virtual void CloseIdleSockets() {}
498  virtual int IdleSocketCount() const {
499    return 0;
500  }
501  virtual int IdleSocketCountInGroup(const std::string& group_name) const {
502    return 0;
503  }
504  virtual LoadState GetLoadState(const std::string& group_name,
505                                 const ClientSocketHandle* handle) const {
506    return LOAD_STATE_IDLE;
507  }
508  virtual base::TimeDelta ConnectionTimeout() const {
509    return base::TimeDelta();
510  }
511
512 private:
513  std::string last_group_name_;
514};
515
516typedef CaptureGroupNameSocketPool<TransportClientSocketPool>
517CaptureGroupNameTransportSocketPool;
518typedef CaptureGroupNameSocketPool<HttpProxyClientSocketPool>
519CaptureGroupNameHttpProxySocketPool;
520typedef CaptureGroupNameSocketPool<SOCKSClientSocketPool>
521CaptureGroupNameSOCKSSocketPool;
522typedef CaptureGroupNameSocketPool<SSLClientSocketPool>
523CaptureGroupNameSSLSocketPool;
524
525template<typename ParentPool>
526CaptureGroupNameSocketPool<ParentPool>::CaptureGroupNameSocketPool(
527    HostResolver* host_resolver,
528    CertVerifier* /* cert_verifier */)
529    : ParentPool(0, 0, NULL, host_resolver, NULL, NULL) {}
530
531template<>
532CaptureGroupNameHttpProxySocketPool::CaptureGroupNameSocketPool(
533    HostResolver* host_resolver,
534    CertVerifier* /* cert_verifier */)
535    : HttpProxyClientSocketPool(0, 0, NULL, host_resolver, NULL, NULL, NULL) {}
536
537template <>
538CaptureGroupNameSSLSocketPool::CaptureGroupNameSocketPool(
539    HostResolver* host_resolver,
540    CertVerifier* cert_verifier)
541    : SSLClientSocketPool(0,
542                          0,
543                          NULL,
544                          host_resolver,
545                          cert_verifier,
546                          NULL,
547                          NULL,
548                          NULL,
549                          std::string(),
550                          NULL,
551                          NULL,
552                          NULL,
553                          NULL,
554                          NULL,
555                          NULL) {}
556
557//-----------------------------------------------------------------------------
558
559// Helper functions for validating that AuthChallengeInfo's are correctly
560// configured for common cases.
561bool CheckBasicServerAuth(const AuthChallengeInfo* auth_challenge) {
562  if (!auth_challenge)
563    return false;
564  EXPECT_FALSE(auth_challenge->is_proxy);
565  EXPECT_EQ("www.google.com:80", auth_challenge->challenger.ToString());
566  EXPECT_EQ("MyRealm1", auth_challenge->realm);
567  EXPECT_EQ("basic", auth_challenge->scheme);
568  return true;
569}
570
571bool CheckBasicProxyAuth(const AuthChallengeInfo* auth_challenge) {
572  if (!auth_challenge)
573    return false;
574  EXPECT_TRUE(auth_challenge->is_proxy);
575  EXPECT_EQ("myproxy:70", auth_challenge->challenger.ToString());
576  EXPECT_EQ("MyRealm1", auth_challenge->realm);
577  EXPECT_EQ("basic", auth_challenge->scheme);
578  return true;
579}
580
581bool CheckDigestServerAuth(const AuthChallengeInfo* auth_challenge) {
582  if (!auth_challenge)
583    return false;
584  EXPECT_FALSE(auth_challenge->is_proxy);
585  EXPECT_EQ("www.google.com:80", auth_challenge->challenger.ToString());
586  EXPECT_EQ("digestive", auth_challenge->realm);
587  EXPECT_EQ("digest", auth_challenge->scheme);
588  return true;
589}
590
591bool CheckNTLMServerAuth(const AuthChallengeInfo* auth_challenge) {
592  if (!auth_challenge)
593    return false;
594  EXPECT_FALSE(auth_challenge->is_proxy);
595  EXPECT_EQ("172.22.68.17:80", auth_challenge->challenger.ToString());
596  EXPECT_EQ(std::string(), auth_challenge->realm);
597  EXPECT_EQ("ntlm", auth_challenge->scheme);
598  return true;
599}
600
601}  // namespace
602
603TEST_P(HttpNetworkTransactionTest, Basic) {
604  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
605  scoped_ptr<HttpTransaction> trans(
606      new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
607}
608
609TEST_P(HttpNetworkTransactionTest, SimpleGET) {
610  MockRead data_reads[] = {
611    MockRead("HTTP/1.0 200 OK\r\n\r\n"),
612    MockRead("hello world"),
613    MockRead(SYNCHRONOUS, OK),
614  };
615  SimpleGetHelperResult out = SimpleGetHelper(data_reads,
616                                              arraysize(data_reads));
617  EXPECT_EQ(OK, out.rv);
618  EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
619  EXPECT_EQ("hello world", out.response_data);
620  int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
621  EXPECT_EQ(reads_size, out.totalReceivedBytes);
622}
623
624// Response with no status line.
625TEST_P(HttpNetworkTransactionTest, SimpleGETNoHeaders) {
626  MockRead data_reads[] = {
627    MockRead("hello world"),
628    MockRead(SYNCHRONOUS, OK),
629  };
630  SimpleGetHelperResult out = SimpleGetHelper(data_reads,
631                                              arraysize(data_reads));
632  EXPECT_EQ(OK, out.rv);
633  EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
634  EXPECT_EQ("hello world", out.response_data);
635  int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
636  EXPECT_EQ(reads_size, out.totalReceivedBytes);
637}
638
639// Allow up to 4 bytes of junk to precede status line.
640TEST_P(HttpNetworkTransactionTest, StatusLineJunk3Bytes) {
641  MockRead data_reads[] = {
642    MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
643    MockRead(SYNCHRONOUS, OK),
644  };
645  SimpleGetHelperResult out = SimpleGetHelper(data_reads,
646                                              arraysize(data_reads));
647  EXPECT_EQ(OK, out.rv);
648  EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
649  EXPECT_EQ("DATA", out.response_data);
650  int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
651  EXPECT_EQ(reads_size, out.totalReceivedBytes);
652}
653
654// Allow up to 4 bytes of junk to precede status line.
655TEST_P(HttpNetworkTransactionTest, StatusLineJunk4Bytes) {
656  MockRead data_reads[] = {
657    MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
658    MockRead(SYNCHRONOUS, OK),
659  };
660  SimpleGetHelperResult out = SimpleGetHelper(data_reads,
661                                              arraysize(data_reads));
662  EXPECT_EQ(OK, out.rv);
663  EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
664  EXPECT_EQ("DATA", out.response_data);
665  int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
666  EXPECT_EQ(reads_size, out.totalReceivedBytes);
667}
668
669// Beyond 4 bytes of slop and it should fail to find a status line.
670TEST_P(HttpNetworkTransactionTest, StatusLineJunk5Bytes) {
671  MockRead data_reads[] = {
672    MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
673    MockRead(SYNCHRONOUS, OK),
674  };
675  SimpleGetHelperResult out = SimpleGetHelper(data_reads,
676                                              arraysize(data_reads));
677  EXPECT_EQ(OK, out.rv);
678  EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
679  EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data);
680  int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
681  EXPECT_EQ(reads_size, out.totalReceivedBytes);
682}
683
684// Same as StatusLineJunk4Bytes, except the read chunks are smaller.
685TEST_P(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) {
686  MockRead data_reads[] = {
687    MockRead("\n"),
688    MockRead("\n"),
689    MockRead("Q"),
690    MockRead("J"),
691    MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
692    MockRead(SYNCHRONOUS, OK),
693  };
694  SimpleGetHelperResult out = SimpleGetHelper(data_reads,
695                                              arraysize(data_reads));
696  EXPECT_EQ(OK, out.rv);
697  EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
698  EXPECT_EQ("DATA", out.response_data);
699  int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
700  EXPECT_EQ(reads_size, out.totalReceivedBytes);
701}
702
703// Close the connection before enough bytes to have a status line.
704TEST_P(HttpNetworkTransactionTest, StatusLinePartial) {
705  MockRead data_reads[] = {
706    MockRead("HTT"),
707    MockRead(SYNCHRONOUS, OK),
708  };
709  SimpleGetHelperResult out = SimpleGetHelper(data_reads,
710                                              arraysize(data_reads));
711  EXPECT_EQ(OK, out.rv);
712  EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
713  EXPECT_EQ("HTT", out.response_data);
714  int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
715  EXPECT_EQ(reads_size, out.totalReceivedBytes);
716}
717
718// Simulate a 204 response, lacking a Content-Length header, sent over a
719// persistent connection.  The response should still terminate since a 204
720// cannot have a response body.
721TEST_P(HttpNetworkTransactionTest, StopsReading204) {
722  char junk[] = "junk";
723  MockRead data_reads[] = {
724    MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
725    MockRead(junk),  // Should not be read!!
726    MockRead(SYNCHRONOUS, OK),
727  };
728  SimpleGetHelperResult out = SimpleGetHelper(data_reads,
729                                              arraysize(data_reads));
730  EXPECT_EQ(OK, out.rv);
731  EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line);
732  EXPECT_EQ("", out.response_data);
733  int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
734  int64 response_size = reads_size - strlen(junk);
735  EXPECT_EQ(response_size, out.totalReceivedBytes);
736}
737
738// A simple request using chunked encoding with some extra data after.
739// (Like might be seen in a pipelined response.)
740TEST_P(HttpNetworkTransactionTest, ChunkedEncoding) {
741  std::string final_chunk = "0\r\n\r\n";
742  std::string extra_data = "HTTP/1.1 200 OK\r\n";
743  std::string last_read = final_chunk + extra_data;
744  MockRead data_reads[] = {
745    MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
746    MockRead("5\r\nHello\r\n"),
747    MockRead("1\r\n"),
748    MockRead(" \r\n"),
749    MockRead("5\r\nworld\r\n"),
750    MockRead(last_read.data()),
751    MockRead(SYNCHRONOUS, OK),
752  };
753  SimpleGetHelperResult out = SimpleGetHelper(data_reads,
754                                              arraysize(data_reads));
755  EXPECT_EQ(OK, out.rv);
756  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
757  EXPECT_EQ("Hello world", out.response_data);
758  int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
759  int64 response_size = reads_size - extra_data.size();
760  EXPECT_EQ(response_size, out.totalReceivedBytes);
761}
762
763// Next tests deal with http://crbug.com/56344.
764
765TEST_P(HttpNetworkTransactionTest,
766       MultipleContentLengthHeadersNoTransferEncoding) {
767  MockRead data_reads[] = {
768    MockRead("HTTP/1.1 200 OK\r\n"),
769    MockRead("Content-Length: 10\r\n"),
770    MockRead("Content-Length: 5\r\n\r\n"),
771  };
772  SimpleGetHelperResult out = SimpleGetHelper(data_reads,
773                                              arraysize(data_reads));
774  EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, out.rv);
775}
776
777TEST_P(HttpNetworkTransactionTest,
778       DuplicateContentLengthHeadersNoTransferEncoding) {
779  MockRead data_reads[] = {
780    MockRead("HTTP/1.1 200 OK\r\n"),
781    MockRead("Content-Length: 5\r\n"),
782    MockRead("Content-Length: 5\r\n\r\n"),
783    MockRead("Hello"),
784  };
785  SimpleGetHelperResult out = SimpleGetHelper(data_reads,
786                                              arraysize(data_reads));
787  EXPECT_EQ(OK, out.rv);
788  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
789  EXPECT_EQ("Hello", out.response_data);
790}
791
792TEST_P(HttpNetworkTransactionTest,
793       ComplexContentLengthHeadersNoTransferEncoding) {
794  // More than 2 dupes.
795  {
796    MockRead data_reads[] = {
797      MockRead("HTTP/1.1 200 OK\r\n"),
798      MockRead("Content-Length: 5\r\n"),
799      MockRead("Content-Length: 5\r\n"),
800      MockRead("Content-Length: 5\r\n\r\n"),
801      MockRead("Hello"),
802    };
803    SimpleGetHelperResult out = SimpleGetHelper(data_reads,
804                                                arraysize(data_reads));
805    EXPECT_EQ(OK, out.rv);
806    EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
807    EXPECT_EQ("Hello", out.response_data);
808  }
809  // HTTP/1.0
810  {
811    MockRead data_reads[] = {
812      MockRead("HTTP/1.0 200 OK\r\n"),
813      MockRead("Content-Length: 5\r\n"),
814      MockRead("Content-Length: 5\r\n"),
815      MockRead("Content-Length: 5\r\n\r\n"),
816      MockRead("Hello"),
817    };
818    SimpleGetHelperResult out = SimpleGetHelper(data_reads,
819                                                arraysize(data_reads));
820    EXPECT_EQ(OK, out.rv);
821    EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
822    EXPECT_EQ("Hello", out.response_data);
823  }
824  // 2 dupes and one mismatched.
825  {
826    MockRead data_reads[] = {
827      MockRead("HTTP/1.1 200 OK\r\n"),
828      MockRead("Content-Length: 10\r\n"),
829      MockRead("Content-Length: 10\r\n"),
830      MockRead("Content-Length: 5\r\n\r\n"),
831    };
832    SimpleGetHelperResult out = SimpleGetHelper(data_reads,
833                                                arraysize(data_reads));
834    EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, out.rv);
835  }
836}
837
838TEST_P(HttpNetworkTransactionTest,
839       MultipleContentLengthHeadersTransferEncoding) {
840  MockRead data_reads[] = {
841    MockRead("HTTP/1.1 200 OK\r\n"),
842    MockRead("Content-Length: 666\r\n"),
843    MockRead("Content-Length: 1337\r\n"),
844    MockRead("Transfer-Encoding: chunked\r\n\r\n"),
845    MockRead("5\r\nHello\r\n"),
846    MockRead("1\r\n"),
847    MockRead(" \r\n"),
848    MockRead("5\r\nworld\r\n"),
849    MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
850    MockRead(SYNCHRONOUS, OK),
851  };
852  SimpleGetHelperResult out = SimpleGetHelper(data_reads,
853                                              arraysize(data_reads));
854  EXPECT_EQ(OK, out.rv);
855  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
856  EXPECT_EQ("Hello world", out.response_data);
857}
858
859// Next tests deal with http://crbug.com/98895.
860
861// Checks that a single Content-Disposition header results in no error.
862TEST_P(HttpNetworkTransactionTest, SingleContentDispositionHeader) {
863  MockRead data_reads[] = {
864    MockRead("HTTP/1.1 200 OK\r\n"),
865    MockRead("Content-Disposition: attachment;filename=\"salutations.txt\"r\n"),
866    MockRead("Content-Length: 5\r\n\r\n"),
867    MockRead("Hello"),
868  };
869  SimpleGetHelperResult out = SimpleGetHelper(data_reads,
870                                              arraysize(data_reads));
871  EXPECT_EQ(OK, out.rv);
872  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
873  EXPECT_EQ("Hello", out.response_data);
874}
875
876// Checks that two identical Content-Disposition headers result in no error.
877TEST_P(HttpNetworkTransactionTest,
878       TwoIdenticalContentDispositionHeaders) {
879  MockRead data_reads[] = {
880    MockRead("HTTP/1.1 200 OK\r\n"),
881    MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
882    MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
883    MockRead("Content-Length: 5\r\n\r\n"),
884    MockRead("Hello"),
885  };
886  SimpleGetHelperResult out = SimpleGetHelper(data_reads,
887                                              arraysize(data_reads));
888  EXPECT_EQ(OK, out.rv);
889  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
890  EXPECT_EQ("Hello", out.response_data);
891}
892
893// Checks that two distinct Content-Disposition headers result in an error.
894TEST_P(HttpNetworkTransactionTest, TwoDistinctContentDispositionHeaders) {
895  MockRead data_reads[] = {
896    MockRead("HTTP/1.1 200 OK\r\n"),
897    MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
898    MockRead("Content-Disposition: attachment;filename=\"hi.txt\"r\n"),
899    MockRead("Content-Length: 5\r\n\r\n"),
900    MockRead("Hello"),
901  };
902  SimpleGetHelperResult out = SimpleGetHelper(data_reads,
903                                              arraysize(data_reads));
904  EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION, out.rv);
905}
906
907// Checks that two identical Location headers result in no error.
908// Also tests Location header behavior.
909TEST_P(HttpNetworkTransactionTest, TwoIdenticalLocationHeaders) {
910  MockRead data_reads[] = {
911    MockRead("HTTP/1.1 302 Redirect\r\n"),
912    MockRead("Location: http://good.com/\r\n"),
913    MockRead("Location: http://good.com/\r\n"),
914    MockRead("Content-Length: 0\r\n\r\n"),
915    MockRead(SYNCHRONOUS, OK),
916  };
917
918  HttpRequestInfo request;
919  request.method = "GET";
920  request.url = GURL("http://redirect.com/");
921  request.load_flags = 0;
922
923  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
924  scoped_ptr<HttpTransaction> trans(
925      new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
926
927  StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
928  session_deps_.socket_factory->AddSocketDataProvider(&data);
929
930  TestCompletionCallback callback;
931
932  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
933  EXPECT_EQ(ERR_IO_PENDING, rv);
934
935  EXPECT_EQ(OK, callback.WaitForResult());
936
937  const HttpResponseInfo* response = trans->GetResponseInfo();
938  ASSERT_TRUE(response != NULL && response->headers.get() != NULL);
939  EXPECT_EQ("HTTP/1.1 302 Redirect", response->headers->GetStatusLine());
940  std::string url;
941  EXPECT_TRUE(response->headers->IsRedirect(&url));
942  EXPECT_EQ("http://good.com/", url);
943}
944
945// Checks that two distinct Location headers result in an error.
946TEST_P(HttpNetworkTransactionTest, TwoDistinctLocationHeaders) {
947  MockRead data_reads[] = {
948    MockRead("HTTP/1.1 302 Redirect\r\n"),
949    MockRead("Location: http://good.com/\r\n"),
950    MockRead("Location: http://evil.com/\r\n"),
951    MockRead("Content-Length: 0\r\n\r\n"),
952    MockRead(SYNCHRONOUS, OK),
953  };
954  SimpleGetHelperResult out = SimpleGetHelper(data_reads,
955                                              arraysize(data_reads));
956  EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_LOCATION, out.rv);
957}
958
959// Do a request using the HEAD method. Verify that we don't try to read the
960// message body (since HEAD has none).
961TEST_P(HttpNetworkTransactionTest, Head) {
962  HttpRequestInfo request;
963  request.method = "HEAD";
964  request.url = GURL("http://www.google.com/");
965  request.load_flags = 0;
966
967  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
968  scoped_ptr<HttpTransaction> trans(
969      new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
970
971  MockWrite data_writes1[] = {
972    MockWrite("HEAD / HTTP/1.1\r\n"
973              "Host: www.google.com\r\n"
974              "Connection: keep-alive\r\n"
975              "Content-Length: 0\r\n\r\n"),
976  };
977  MockRead data_reads1[] = {
978    MockRead("HTTP/1.1 404 Not Found\r\n"),
979    MockRead("Server: Blah\r\n"),
980    MockRead("Content-Length: 1234\r\n\r\n"),
981
982    // No response body because the test stops reading here.
983    MockRead(SYNCHRONOUS, ERR_UNEXPECTED),  // Should not be reached.
984  };
985
986  StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
987                                 data_writes1, arraysize(data_writes1));
988  session_deps_.socket_factory->AddSocketDataProvider(&data1);
989
990  TestCompletionCallback callback1;
991
992  int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
993  EXPECT_EQ(ERR_IO_PENDING, rv);
994
995  rv = callback1.WaitForResult();
996  EXPECT_EQ(OK, rv);
997
998  const HttpResponseInfo* response = trans->GetResponseInfo();
999  ASSERT_TRUE(response != NULL);
1000
1001  // Check that the headers got parsed.
1002  EXPECT_TRUE(response->headers.get() != NULL);
1003  EXPECT_EQ(1234, response->headers->GetContentLength());
1004  EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine());
1005
1006  std::string server_header;
1007  void* iter = NULL;
1008  bool has_server_header = response->headers->EnumerateHeader(
1009      &iter, "Server", &server_header);
1010  EXPECT_TRUE(has_server_header);
1011  EXPECT_EQ("Blah", server_header);
1012
1013  // Reading should give EOF right away, since there is no message body
1014  // (despite non-zero content-length).
1015  std::string response_data;
1016  rv = ReadTransaction(trans.get(), &response_data);
1017  EXPECT_EQ(OK, rv);
1018  EXPECT_EQ("", response_data);
1019}
1020
1021TEST_P(HttpNetworkTransactionTest, ReuseConnection) {
1022  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1023
1024  MockRead data_reads[] = {
1025    MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1026    MockRead("hello"),
1027    MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1028    MockRead("world"),
1029    MockRead(SYNCHRONOUS, OK),
1030  };
1031  StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1032  session_deps_.socket_factory->AddSocketDataProvider(&data);
1033
1034  const char* const kExpectedResponseData[] = {
1035    "hello", "world"
1036  };
1037
1038  for (int i = 0; i < 2; ++i) {
1039    HttpRequestInfo request;
1040    request.method = "GET";
1041    request.url = GURL("http://www.google.com/");
1042    request.load_flags = 0;
1043
1044    scoped_ptr<HttpTransaction> trans(
1045        new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1046
1047    TestCompletionCallback callback;
1048
1049    int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1050    EXPECT_EQ(ERR_IO_PENDING, rv);
1051
1052    rv = callback.WaitForResult();
1053    EXPECT_EQ(OK, rv);
1054
1055    const HttpResponseInfo* response = trans->GetResponseInfo();
1056    ASSERT_TRUE(response != NULL);
1057
1058    EXPECT_TRUE(response->headers.get() != NULL);
1059    EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1060
1061    std::string response_data;
1062    rv = ReadTransaction(trans.get(), &response_data);
1063    EXPECT_EQ(OK, rv);
1064    EXPECT_EQ(kExpectedResponseData[i], response_data);
1065  }
1066}
1067
1068TEST_P(HttpNetworkTransactionTest, Ignores100) {
1069  ScopedVector<UploadElementReader> element_readers;
1070  element_readers.push_back(new UploadBytesElementReader("foo", 3));
1071  UploadDataStream upload_data_stream(element_readers.Pass(), 0);
1072
1073  HttpRequestInfo request;
1074  request.method = "POST";
1075  request.url = GURL("http://www.foo.com/");
1076  request.upload_data_stream = &upload_data_stream;
1077  request.load_flags = 0;
1078
1079  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1080  scoped_ptr<HttpTransaction> trans(
1081      new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
1082
1083  MockRead data_reads[] = {
1084    MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
1085    MockRead("HTTP/1.0 200 OK\r\n\r\n"),
1086    MockRead("hello world"),
1087    MockRead(SYNCHRONOUS, OK),
1088  };
1089  StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1090  session_deps_.socket_factory->AddSocketDataProvider(&data);
1091
1092  TestCompletionCallback callback;
1093
1094  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1095  EXPECT_EQ(ERR_IO_PENDING, rv);
1096
1097  rv = callback.WaitForResult();
1098  EXPECT_EQ(OK, rv);
1099
1100  const HttpResponseInfo* response = trans->GetResponseInfo();
1101  ASSERT_TRUE(response != NULL);
1102
1103  EXPECT_TRUE(response->headers.get() != NULL);
1104  EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
1105
1106  std::string response_data;
1107  rv = ReadTransaction(trans.get(), &response_data);
1108  EXPECT_EQ(OK, rv);
1109  EXPECT_EQ("hello world", response_data);
1110}
1111
1112// This test is almost the same as Ignores100 above, but the response contains
1113// a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
1114// HTTP/1.1 and the two status headers are read in one read.
1115TEST_P(HttpNetworkTransactionTest, Ignores1xx) {
1116  HttpRequestInfo request;
1117  request.method = "GET";
1118  request.url = GURL("http://www.foo.com/");
1119  request.load_flags = 0;
1120
1121  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1122  scoped_ptr<HttpTransaction> trans(
1123      new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
1124
1125  MockRead data_reads[] = {
1126    MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
1127             "HTTP/1.1 200 OK\r\n\r\n"),
1128    MockRead("hello world"),
1129    MockRead(SYNCHRONOUS, OK),
1130  };
1131  StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1132  session_deps_.socket_factory->AddSocketDataProvider(&data);
1133
1134  TestCompletionCallback callback;
1135
1136  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1137  EXPECT_EQ(ERR_IO_PENDING, rv);
1138
1139  rv = callback.WaitForResult();
1140  EXPECT_EQ(OK, rv);
1141
1142  const HttpResponseInfo* response = trans->GetResponseInfo();
1143  ASSERT_TRUE(response != NULL);
1144
1145  EXPECT_TRUE(response->headers.get() != NULL);
1146  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1147
1148  std::string response_data;
1149  rv = ReadTransaction(trans.get(), &response_data);
1150  EXPECT_EQ(OK, rv);
1151  EXPECT_EQ("hello world", response_data);
1152}
1153
1154TEST_P(HttpNetworkTransactionTest, Incomplete100ThenEOF) {
1155  HttpRequestInfo request;
1156  request.method = "POST";
1157  request.url = GURL("http://www.foo.com/");
1158  request.load_flags = 0;
1159
1160  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1161  scoped_ptr<HttpTransaction> trans(
1162      new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
1163
1164  MockRead data_reads[] = {
1165    MockRead(SYNCHRONOUS, "HTTP/1.0 100 Continue\r\n"),
1166    MockRead(ASYNC, 0),
1167  };
1168  StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1169  session_deps_.socket_factory->AddSocketDataProvider(&data);
1170
1171  TestCompletionCallback callback;
1172
1173  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1174  EXPECT_EQ(ERR_IO_PENDING, rv);
1175
1176  rv = callback.WaitForResult();
1177  EXPECT_EQ(OK, rv);
1178
1179  std::string response_data;
1180  rv = ReadTransaction(trans.get(), &response_data);
1181  EXPECT_EQ(OK, rv);
1182  EXPECT_EQ("", response_data);
1183}
1184
1185TEST_P(HttpNetworkTransactionTest, EmptyResponse) {
1186  HttpRequestInfo request;
1187  request.method = "POST";
1188  request.url = GURL("http://www.foo.com/");
1189  request.load_flags = 0;
1190
1191  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1192  scoped_ptr<HttpTransaction> trans(
1193      new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
1194
1195
1196  MockRead data_reads[] = {
1197    MockRead(ASYNC, 0),
1198  };
1199  StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1200  session_deps_.socket_factory->AddSocketDataProvider(&data);
1201
1202  TestCompletionCallback callback;
1203
1204  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1205  EXPECT_EQ(ERR_IO_PENDING, rv);
1206
1207  rv = callback.WaitForResult();
1208  EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
1209}
1210
1211void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
1212    const MockWrite* write_failure,
1213    const MockRead* read_failure) {
1214  HttpRequestInfo request;
1215  request.method = "GET";
1216  request.url = GURL("http://www.foo.com/");
1217  request.load_flags = 0;
1218
1219  CapturingNetLog net_log;
1220  session_deps_.net_log = &net_log;
1221  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1222
1223  // Written data for successfully sending both requests.
1224  MockWrite data1_writes[] = {
1225    MockWrite("GET / HTTP/1.1\r\n"
1226              "Host: www.foo.com\r\n"
1227              "Connection: keep-alive\r\n\r\n"),
1228    MockWrite("GET / HTTP/1.1\r\n"
1229              "Host: www.foo.com\r\n"
1230              "Connection: keep-alive\r\n\r\n")
1231  };
1232
1233  // Read results for the first request.
1234  MockRead data1_reads[] = {
1235    MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1236    MockRead("hello"),
1237    MockRead(ASYNC, OK),
1238  };
1239
1240  if (write_failure) {
1241    ASSERT_TRUE(!read_failure);
1242    data1_writes[1] = *write_failure;
1243  } else {
1244    ASSERT_TRUE(read_failure);
1245    data1_reads[2] = *read_failure;
1246  }
1247
1248  StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads),
1249                                 data1_writes, arraysize(data1_writes));
1250  session_deps_.socket_factory->AddSocketDataProvider(&data1);
1251
1252  MockRead data2_reads[] = {
1253    MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1254    MockRead("world"),
1255    MockRead(ASYNC, OK),
1256  };
1257  StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
1258  session_deps_.socket_factory->AddSocketDataProvider(&data2);
1259
1260  const char* kExpectedResponseData[] = {
1261    "hello", "world"
1262  };
1263
1264  uint32 first_socket_log_id = NetLog::Source::kInvalidId;
1265  for (int i = 0; i < 2; ++i) {
1266    TestCompletionCallback callback;
1267
1268    scoped_ptr<HttpTransaction> trans(
1269        new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1270
1271    int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1272    EXPECT_EQ(ERR_IO_PENDING, rv);
1273
1274    rv = callback.WaitForResult();
1275    EXPECT_EQ(OK, rv);
1276
1277    LoadTimingInfo load_timing_info;
1278    EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
1279    TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
1280    if (i == 0) {
1281      first_socket_log_id = load_timing_info.socket_log_id;
1282    } else {
1283      // The second request should be using a new socket.
1284      EXPECT_NE(first_socket_log_id, load_timing_info.socket_log_id);
1285    }
1286
1287    const HttpResponseInfo* response = trans->GetResponseInfo();
1288    ASSERT_TRUE(response != NULL);
1289
1290    EXPECT_TRUE(response->headers.get() != NULL);
1291    EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1292
1293    std::string response_data;
1294    rv = ReadTransaction(trans.get(), &response_data);
1295    EXPECT_EQ(OK, rv);
1296    EXPECT_EQ(kExpectedResponseData[i], response_data);
1297  }
1298}
1299
1300TEST_P(HttpNetworkTransactionTest,
1301       KeepAliveConnectionNotConnectedOnWrite) {
1302  MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
1303  KeepAliveConnectionResendRequestTest(&write_failure, NULL);
1304}
1305
1306TEST_P(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
1307  MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
1308  KeepAliveConnectionResendRequestTest(NULL, &read_failure);
1309}
1310
1311TEST_P(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
1312  MockRead read_failure(SYNCHRONOUS, OK);  // EOF
1313  KeepAliveConnectionResendRequestTest(NULL, &read_failure);
1314}
1315
1316TEST_P(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
1317  HttpRequestInfo request;
1318  request.method = "GET";
1319  request.url = GURL("http://www.google.com/");
1320  request.load_flags = 0;
1321
1322  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1323  scoped_ptr<HttpTransaction> trans(
1324      new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
1325
1326  MockRead data_reads[] = {
1327    MockRead(ASYNC, ERR_CONNECTION_RESET),
1328    MockRead("HTTP/1.0 200 OK\r\n\r\n"),  // Should not be used
1329    MockRead("hello world"),
1330    MockRead(SYNCHRONOUS, OK),
1331  };
1332  StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1333  session_deps_.socket_factory->AddSocketDataProvider(&data);
1334
1335  TestCompletionCallback callback;
1336
1337  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1338  EXPECT_EQ(ERR_IO_PENDING, rv);
1339
1340  rv = callback.WaitForResult();
1341  EXPECT_EQ(ERR_CONNECTION_RESET, rv);
1342
1343  const HttpResponseInfo* response = trans->GetResponseInfo();
1344  EXPECT_TRUE(response == NULL);
1345}
1346
1347// What do various browsers do when the server closes a non-keepalive
1348// connection without sending any response header or body?
1349//
1350// IE7: error page
1351// Safari 3.1.2 (Windows): error page
1352// Firefox 3.0.1: blank page
1353// Opera 9.52: after five attempts, blank page
1354// Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
1355// Us: error page (EMPTY_RESPONSE)
1356TEST_P(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
1357  MockRead data_reads[] = {
1358    MockRead(SYNCHRONOUS, OK),  // EOF
1359    MockRead("HTTP/1.0 200 OK\r\n\r\n"),  // Should not be used
1360    MockRead("hello world"),
1361    MockRead(SYNCHRONOUS, OK),
1362  };
1363  SimpleGetHelperResult out = SimpleGetHelper(data_reads,
1364                                              arraysize(data_reads));
1365  EXPECT_EQ(ERR_EMPTY_RESPONSE, out.rv);
1366}
1367
1368// Test that network access can be deferred and resumed.
1369TEST_P(HttpNetworkTransactionTest, ThrottleBeforeNetworkStart) {
1370  HttpRequestInfo request;
1371  request.method = "GET";
1372  request.url = GURL("http://www.google.com/");
1373  request.load_flags = 0;
1374
1375  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1376  scoped_ptr<HttpTransaction> trans(
1377      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1378
1379  // Defer on OnBeforeNetworkStart.
1380  BeforeNetworkStartHandler net_start_handler(true);  // defer
1381  trans->SetBeforeNetworkStartCallback(
1382      base::Bind(&BeforeNetworkStartHandler::OnBeforeNetworkStart,
1383                 base::Unretained(&net_start_handler)));
1384
1385  MockRead data_reads[] = {
1386    MockRead("HTTP/1.0 200 OK\r\n"),
1387    MockRead("Content-Length: 5\r\n\r\n"),
1388    MockRead("hello"),
1389    MockRead(SYNCHRONOUS, 0),
1390  };
1391  StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1392  session_deps_.socket_factory->AddSocketDataProvider(&data);
1393
1394  TestCompletionCallback callback;
1395
1396  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1397  EXPECT_EQ(ERR_IO_PENDING, rv);
1398  base::MessageLoop::current()->RunUntilIdle();
1399
1400  // Should have deferred for network start.
1401  EXPECT_TRUE(net_start_handler.observed_before_network_start());
1402  EXPECT_EQ(LOAD_STATE_WAITING_FOR_DELEGATE, trans->GetLoadState());
1403  EXPECT_TRUE(trans->GetResponseInfo() == NULL);
1404
1405  trans->ResumeNetworkStart();
1406  rv = callback.WaitForResult();
1407  EXPECT_EQ(OK, rv);
1408  EXPECT_TRUE(trans->GetResponseInfo() != NULL);
1409
1410  scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(100));
1411  rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
1412  if (rv == ERR_IO_PENDING)
1413    rv = callback.WaitForResult();
1414  EXPECT_EQ(5, rv);
1415  trans.reset();
1416}
1417
1418// Test that network use can be deferred and canceled.
1419TEST_P(HttpNetworkTransactionTest, ThrottleAndCancelBeforeNetworkStart) {
1420  HttpRequestInfo request;
1421  request.method = "GET";
1422  request.url = GURL("http://www.google.com/");
1423  request.load_flags = 0;
1424
1425  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1426  scoped_ptr<HttpTransaction> trans(
1427      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1428
1429  // Defer on OnBeforeNetworkStart.
1430  BeforeNetworkStartHandler net_start_handler(true);  // defer
1431  trans->SetBeforeNetworkStartCallback(
1432      base::Bind(&BeforeNetworkStartHandler::OnBeforeNetworkStart,
1433                 base::Unretained(&net_start_handler)));
1434
1435  TestCompletionCallback callback;
1436
1437  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1438  EXPECT_EQ(ERR_IO_PENDING, rv);
1439  base::MessageLoop::current()->RunUntilIdle();
1440
1441  // Should have deferred for network start.
1442  EXPECT_TRUE(net_start_handler.observed_before_network_start());
1443  EXPECT_EQ(LOAD_STATE_WAITING_FOR_DELEGATE, trans->GetLoadState());
1444  EXPECT_TRUE(trans->GetResponseInfo() == NULL);
1445}
1446
1447// Next 2 cases (KeepAliveEarlyClose and KeepAliveEarlyClose2) are regression
1448// tests. There was a bug causing HttpNetworkTransaction to hang in the
1449// destructor in such situations.
1450// See http://crbug.com/154712 and http://crbug.com/156609.
1451TEST_P(HttpNetworkTransactionTest, KeepAliveEarlyClose) {
1452  HttpRequestInfo request;
1453  request.method = "GET";
1454  request.url = GURL("http://www.google.com/");
1455  request.load_flags = 0;
1456
1457  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1458  scoped_ptr<HttpTransaction> trans(
1459      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1460
1461  MockRead data_reads[] = {
1462    MockRead("HTTP/1.0 200 OK\r\n"),
1463    MockRead("Connection: keep-alive\r\n"),
1464    MockRead("Content-Length: 100\r\n\r\n"),
1465    MockRead("hello"),
1466    MockRead(SYNCHRONOUS, 0),
1467  };
1468  StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1469  session_deps_.socket_factory->AddSocketDataProvider(&data);
1470
1471  TestCompletionCallback callback;
1472
1473  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1474  EXPECT_EQ(ERR_IO_PENDING, rv);
1475
1476  rv = callback.WaitForResult();
1477  EXPECT_EQ(OK, rv);
1478
1479  scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(100));
1480  rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
1481  if (rv == ERR_IO_PENDING)
1482    rv = callback.WaitForResult();
1483  EXPECT_EQ(5, rv);
1484  rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
1485  EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH, rv);
1486
1487  trans.reset();
1488  base::MessageLoop::current()->RunUntilIdle();
1489  EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
1490}
1491
1492TEST_P(HttpNetworkTransactionTest, KeepAliveEarlyClose2) {
1493  HttpRequestInfo request;
1494  request.method = "GET";
1495  request.url = GURL("http://www.google.com/");
1496  request.load_flags = 0;
1497
1498  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1499  scoped_ptr<HttpTransaction> trans(
1500      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1501
1502  MockRead data_reads[] = {
1503    MockRead("HTTP/1.0 200 OK\r\n"),
1504    MockRead("Connection: keep-alive\r\n"),
1505    MockRead("Content-Length: 100\r\n\r\n"),
1506    MockRead(SYNCHRONOUS, 0),
1507  };
1508  StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1509  session_deps_.socket_factory->AddSocketDataProvider(&data);
1510
1511  TestCompletionCallback callback;
1512
1513  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1514  EXPECT_EQ(ERR_IO_PENDING, rv);
1515
1516  rv = callback.WaitForResult();
1517  EXPECT_EQ(OK, rv);
1518
1519  scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(100));
1520  rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
1521  if (rv == ERR_IO_PENDING)
1522    rv = callback.WaitForResult();
1523  EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH, rv);
1524
1525  trans.reset();
1526  base::MessageLoop::current()->RunUntilIdle();
1527  EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
1528}
1529
1530// Test that we correctly reuse a keep-alive connection after not explicitly
1531// reading the body.
1532TEST_P(HttpNetworkTransactionTest, KeepAliveAfterUnreadBody) {
1533  HttpRequestInfo request;
1534  request.method = "GET";
1535  request.url = GURL("http://www.foo.com/");
1536  request.load_flags = 0;
1537
1538  CapturingNetLog net_log;
1539  session_deps_.net_log = &net_log;
1540  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1541
1542  // Note that because all these reads happen in the same
1543  // StaticSocketDataProvider, it shows that the same socket is being reused for
1544  // all transactions.
1545  MockRead data1_reads[] = {
1546    MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
1547    MockRead("HTTP/1.1 205 Reset Content\r\n\r\n"),
1548    MockRead("HTTP/1.1 304 Not Modified\r\n\r\n"),
1549    MockRead("HTTP/1.1 302 Found\r\n"
1550             "Content-Length: 0\r\n\r\n"),
1551    MockRead("HTTP/1.1 302 Found\r\n"
1552             "Content-Length: 5\r\n\r\n"
1553             "hello"),
1554    MockRead("HTTP/1.1 301 Moved Permanently\r\n"
1555             "Content-Length: 0\r\n\r\n"),
1556    MockRead("HTTP/1.1 301 Moved Permanently\r\n"
1557             "Content-Length: 5\r\n\r\n"
1558             "hello"),
1559    MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1560    MockRead("hello"),
1561  };
1562  StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), NULL, 0);
1563  session_deps_.socket_factory->AddSocketDataProvider(&data1);
1564
1565  MockRead data2_reads[] = {
1566    MockRead(SYNCHRONOUS, ERR_UNEXPECTED),  // Should not be reached.
1567  };
1568  StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
1569  session_deps_.socket_factory->AddSocketDataProvider(&data2);
1570
1571  const int kNumUnreadBodies = arraysize(data1_reads) - 2;
1572  std::string response_lines[kNumUnreadBodies];
1573
1574  uint32 first_socket_log_id = NetLog::Source::kInvalidId;
1575  for (size_t i = 0; i < arraysize(data1_reads) - 2; ++i) {
1576    TestCompletionCallback callback;
1577
1578    scoped_ptr<HttpTransaction> trans(
1579        new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1580
1581    int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1582    EXPECT_EQ(ERR_IO_PENDING, rv);
1583
1584    rv = callback.WaitForResult();
1585    EXPECT_EQ(OK, rv);
1586
1587    LoadTimingInfo load_timing_info;
1588    EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
1589    if (i == 0) {
1590      TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
1591      first_socket_log_id = load_timing_info.socket_log_id;
1592    } else {
1593      TestLoadTimingReused(load_timing_info);
1594      EXPECT_EQ(first_socket_log_id, load_timing_info.socket_log_id);
1595    }
1596
1597    const HttpResponseInfo* response = trans->GetResponseInfo();
1598    ASSERT_TRUE(response != NULL);
1599
1600    ASSERT_TRUE(response->headers.get() != NULL);
1601    response_lines[i] = response->headers->GetStatusLine();
1602
1603    // We intentionally don't read the response bodies.
1604  }
1605
1606  const char* const kStatusLines[] = {
1607    "HTTP/1.1 204 No Content",
1608    "HTTP/1.1 205 Reset Content",
1609    "HTTP/1.1 304 Not Modified",
1610    "HTTP/1.1 302 Found",
1611    "HTTP/1.1 302 Found",
1612    "HTTP/1.1 301 Moved Permanently",
1613    "HTTP/1.1 301 Moved Permanently",
1614  };
1615
1616  COMPILE_ASSERT(kNumUnreadBodies == arraysize(kStatusLines),
1617                 forgot_to_update_kStatusLines);
1618
1619  for (int i = 0; i < kNumUnreadBodies; ++i)
1620    EXPECT_EQ(kStatusLines[i], response_lines[i]);
1621
1622  TestCompletionCallback callback;
1623  scoped_ptr<HttpTransaction> trans(
1624      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1625  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1626  EXPECT_EQ(ERR_IO_PENDING, rv);
1627  rv = callback.WaitForResult();
1628  EXPECT_EQ(OK, rv);
1629  const HttpResponseInfo* response = trans->GetResponseInfo();
1630  ASSERT_TRUE(response != NULL);
1631  ASSERT_TRUE(response->headers.get() != NULL);
1632  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1633  std::string response_data;
1634  rv = ReadTransaction(trans.get(), &response_data);
1635  EXPECT_EQ(OK, rv);
1636  EXPECT_EQ("hello", response_data);
1637}
1638
1639// Test the request-challenge-retry sequence for basic auth.
1640// (basic auth is the easiest to mock, because it has no randomness).
1641TEST_P(HttpNetworkTransactionTest, BasicAuth) {
1642  HttpRequestInfo request;
1643  request.method = "GET";
1644  request.url = GURL("http://www.google.com/");
1645  request.load_flags = 0;
1646
1647  CapturingNetLog log;
1648  session_deps_.net_log = &log;
1649  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1650  scoped_ptr<HttpTransaction> trans(
1651      new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
1652
1653  MockWrite data_writes1[] = {
1654    MockWrite("GET / HTTP/1.1\r\n"
1655              "Host: www.google.com\r\n"
1656              "Connection: keep-alive\r\n\r\n"),
1657  };
1658
1659  MockRead data_reads1[] = {
1660    MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1661    // Give a couple authenticate options (only the middle one is actually
1662    // supported).
1663    MockRead("WWW-Authenticate: Basic invalid\r\n"),  // Malformed.
1664    MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1665    MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
1666    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1667    // Large content-length -- won't matter, as connection will be reset.
1668    MockRead("Content-Length: 10000\r\n\r\n"),
1669    MockRead(SYNCHRONOUS, ERR_FAILED),
1670  };
1671
1672  // After calling trans->RestartWithAuth(), this is the request we should
1673  // be issuing -- the final header line contains the credentials.
1674  MockWrite data_writes2[] = {
1675    MockWrite("GET / HTTP/1.1\r\n"
1676              "Host: www.google.com\r\n"
1677              "Connection: keep-alive\r\n"
1678              "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1679  };
1680
1681  // Lastly, the server responds with the actual content.
1682  MockRead data_reads2[] = {
1683    MockRead("HTTP/1.0 200 OK\r\n"),
1684    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1685    MockRead("Content-Length: 100\r\n\r\n"),
1686    MockRead(SYNCHRONOUS, OK),
1687  };
1688
1689  StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1690                                 data_writes1, arraysize(data_writes1));
1691  StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1692                                 data_writes2, arraysize(data_writes2));
1693  session_deps_.socket_factory->AddSocketDataProvider(&data1);
1694  session_deps_.socket_factory->AddSocketDataProvider(&data2);
1695
1696  TestCompletionCallback callback1;
1697
1698  int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
1699  EXPECT_EQ(ERR_IO_PENDING, rv);
1700
1701  rv = callback1.WaitForResult();
1702  EXPECT_EQ(OK, rv);
1703
1704  LoadTimingInfo load_timing_info1;
1705  EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info1));
1706  TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
1707
1708  int64 reads_size1 = ReadsSize(data_reads1, arraysize(data_reads1));
1709  EXPECT_EQ(reads_size1, trans->GetTotalReceivedBytes());
1710
1711  const HttpResponseInfo* response = trans->GetResponseInfo();
1712  ASSERT_TRUE(response != NULL);
1713  EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
1714
1715  TestCompletionCallback callback2;
1716
1717  rv = trans->RestartWithAuth(
1718      AuthCredentials(kFoo, kBar), callback2.callback());
1719  EXPECT_EQ(ERR_IO_PENDING, rv);
1720
1721  rv = callback2.WaitForResult();
1722  EXPECT_EQ(OK, rv);
1723
1724  LoadTimingInfo load_timing_info2;
1725  EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info2));
1726  TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_DNS_TIMES);
1727  // The load timing after restart should have a new socket ID, and times after
1728  // those of the first load timing.
1729  EXPECT_LE(load_timing_info1.receive_headers_end,
1730            load_timing_info2.connect_timing.connect_start);
1731  EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
1732
1733  int64 reads_size2 = ReadsSize(data_reads2, arraysize(data_reads2));
1734  EXPECT_EQ(reads_size1 + reads_size2, trans->GetTotalReceivedBytes());
1735
1736  response = trans->GetResponseInfo();
1737  ASSERT_TRUE(response != NULL);
1738  EXPECT_TRUE(response->auth_challenge.get() == NULL);
1739  EXPECT_EQ(100, response->headers->GetContentLength());
1740}
1741
1742TEST_P(HttpNetworkTransactionTest, DoNotSendAuth) {
1743  HttpRequestInfo request;
1744  request.method = "GET";
1745  request.url = GURL("http://www.google.com/");
1746  request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
1747
1748  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1749  scoped_ptr<HttpTransaction> trans(
1750      new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
1751
1752  MockWrite data_writes[] = {
1753    MockWrite("GET / HTTP/1.1\r\n"
1754              "Host: www.google.com\r\n"
1755              "Connection: keep-alive\r\n\r\n"),
1756  };
1757
1758  MockRead data_reads[] = {
1759    MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1760    MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1761    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1762    // Large content-length -- won't matter, as connection will be reset.
1763    MockRead("Content-Length: 10000\r\n\r\n"),
1764    MockRead(SYNCHRONOUS, ERR_FAILED),
1765  };
1766
1767  StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1768                                data_writes, arraysize(data_writes));
1769  session_deps_.socket_factory->AddSocketDataProvider(&data);
1770  TestCompletionCallback callback;
1771
1772  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1773  EXPECT_EQ(ERR_IO_PENDING, rv);
1774
1775  rv = callback.WaitForResult();
1776  EXPECT_EQ(0, rv);
1777
1778  int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
1779  EXPECT_EQ(reads_size, trans->GetTotalReceivedBytes());
1780
1781  const HttpResponseInfo* response = trans->GetResponseInfo();
1782  ASSERT_TRUE(response != NULL);
1783  EXPECT_TRUE(response->auth_challenge.get() == NULL);
1784}
1785
1786// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1787// connection.
1788TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
1789  HttpRequestInfo request;
1790  request.method = "GET";
1791  request.url = GURL("http://www.google.com/");
1792  request.load_flags = 0;
1793
1794  CapturingNetLog log;
1795  session_deps_.net_log = &log;
1796  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1797
1798  MockWrite data_writes1[] = {
1799    MockWrite("GET / HTTP/1.1\r\n"
1800              "Host: www.google.com\r\n"
1801              "Connection: keep-alive\r\n\r\n"),
1802
1803    // After calling trans->RestartWithAuth(), this is the request we should
1804    // be issuing -- the final header line contains the credentials.
1805    MockWrite("GET / HTTP/1.1\r\n"
1806              "Host: www.google.com\r\n"
1807              "Connection: keep-alive\r\n"
1808              "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1809  };
1810
1811  MockRead data_reads1[] = {
1812    MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1813    MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1814    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1815    MockRead("Content-Length: 14\r\n\r\n"),
1816    MockRead("Unauthorized\r\n"),
1817
1818    // Lastly, the server responds with the actual content.
1819    MockRead("HTTP/1.1 200 OK\r\n"),
1820    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1821    MockRead("Content-Length: 5\r\n\r\n"),
1822    MockRead("Hello"),
1823  };
1824
1825  // If there is a regression where we disconnect a Keep-Alive
1826  // connection during an auth roundtrip, we'll end up reading this.
1827  MockRead data_reads2[] = {
1828    MockRead(SYNCHRONOUS, ERR_FAILED),
1829  };
1830
1831  StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1832                                 data_writes1, arraysize(data_writes1));
1833  StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1834                                 NULL, 0);
1835  session_deps_.socket_factory->AddSocketDataProvider(&data1);
1836  session_deps_.socket_factory->AddSocketDataProvider(&data2);
1837
1838  TestCompletionCallback callback1;
1839
1840  scoped_ptr<HttpTransaction> trans(
1841      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1842  int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
1843  EXPECT_EQ(ERR_IO_PENDING, rv);
1844
1845  rv = callback1.WaitForResult();
1846  EXPECT_EQ(OK, rv);
1847
1848  LoadTimingInfo load_timing_info1;
1849  EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info1));
1850  TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
1851
1852  const HttpResponseInfo* response = trans->GetResponseInfo();
1853  ASSERT_TRUE(response != NULL);
1854  EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
1855
1856  TestCompletionCallback callback2;
1857
1858  rv = trans->RestartWithAuth(
1859      AuthCredentials(kFoo, kBar), callback2.callback());
1860  EXPECT_EQ(ERR_IO_PENDING, rv);
1861
1862  rv = callback2.WaitForResult();
1863  EXPECT_EQ(OK, rv);
1864
1865  LoadTimingInfo load_timing_info2;
1866  EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info2));
1867  TestLoadTimingReused(load_timing_info2);
1868  // The load timing after restart should have the same socket ID, and times
1869  // those of the first load timing.
1870  EXPECT_LE(load_timing_info1.receive_headers_end,
1871            load_timing_info2.send_start);
1872  EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
1873
1874  response = trans->GetResponseInfo();
1875  ASSERT_TRUE(response != NULL);
1876  EXPECT_TRUE(response->auth_challenge.get() == NULL);
1877  EXPECT_EQ(5, response->headers->GetContentLength());
1878
1879  std::string response_data;
1880  rv = ReadTransaction(trans.get(), &response_data);
1881  EXPECT_EQ(OK, rv);
1882  int64 reads_size1 = ReadsSize(data_reads1, arraysize(data_reads1));
1883  EXPECT_EQ(reads_size1, trans->GetTotalReceivedBytes());
1884}
1885
1886// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1887// connection and with no response body to drain.
1888TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
1889  HttpRequestInfo request;
1890  request.method = "GET";
1891  request.url = GURL("http://www.google.com/");
1892  request.load_flags = 0;
1893
1894  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1895
1896  MockWrite data_writes1[] = {
1897    MockWrite("GET / HTTP/1.1\r\n"
1898              "Host: www.google.com\r\n"
1899              "Connection: keep-alive\r\n\r\n"),
1900
1901    // After calling trans->RestartWithAuth(), this is the request we should
1902    // be issuing -- the final header line contains the credentials.
1903    MockWrite("GET / HTTP/1.1\r\n"
1904              "Host: www.google.com\r\n"
1905              "Connection: keep-alive\r\n"
1906              "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1907  };
1908
1909  MockRead data_reads1[] = {
1910    MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1911    MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1912    MockRead("Content-Length: 0\r\n\r\n"),  // No response body.
1913
1914    // Lastly, the server responds with the actual content.
1915    MockRead("HTTP/1.1 200 OK\r\n"),
1916    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1917    MockRead("Content-Length: 5\r\n\r\n"),
1918    MockRead("hello"),
1919  };
1920
1921  // An incorrect reconnect would cause this to be read.
1922  MockRead data_reads2[] = {
1923    MockRead(SYNCHRONOUS, ERR_FAILED),
1924  };
1925
1926  StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1927                                 data_writes1, arraysize(data_writes1));
1928  StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1929                                 NULL, 0);
1930  session_deps_.socket_factory->AddSocketDataProvider(&data1);
1931  session_deps_.socket_factory->AddSocketDataProvider(&data2);
1932
1933  TestCompletionCallback callback1;
1934
1935  scoped_ptr<HttpTransaction> trans(
1936      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1937  int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
1938  EXPECT_EQ(ERR_IO_PENDING, rv);
1939
1940  rv = callback1.WaitForResult();
1941  EXPECT_EQ(OK, rv);
1942
1943  const HttpResponseInfo* response = trans->GetResponseInfo();
1944  ASSERT_TRUE(response != NULL);
1945  EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
1946
1947  TestCompletionCallback callback2;
1948
1949  rv = trans->RestartWithAuth(
1950      AuthCredentials(kFoo, kBar), callback2.callback());
1951  EXPECT_EQ(ERR_IO_PENDING, rv);
1952
1953  rv = callback2.WaitForResult();
1954  EXPECT_EQ(OK, rv);
1955
1956  response = trans->GetResponseInfo();
1957  ASSERT_TRUE(response != NULL);
1958  EXPECT_TRUE(response->auth_challenge.get() == NULL);
1959  EXPECT_EQ(5, response->headers->GetContentLength());
1960}
1961
1962// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1963// connection and with a large response body to drain.
1964TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
1965  HttpRequestInfo request;
1966  request.method = "GET";
1967  request.url = GURL("http://www.google.com/");
1968  request.load_flags = 0;
1969
1970  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1971
1972  MockWrite data_writes1[] = {
1973    MockWrite("GET / HTTP/1.1\r\n"
1974              "Host: www.google.com\r\n"
1975              "Connection: keep-alive\r\n\r\n"),
1976
1977    // After calling trans->RestartWithAuth(), this is the request we should
1978    // be issuing -- the final header line contains the credentials.
1979    MockWrite("GET / HTTP/1.1\r\n"
1980              "Host: www.google.com\r\n"
1981              "Connection: keep-alive\r\n"
1982              "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1983  };
1984
1985  // Respond with 5 kb of response body.
1986  std::string large_body_string("Unauthorized");
1987  large_body_string.append(5 * 1024, ' ');
1988  large_body_string.append("\r\n");
1989
1990  MockRead data_reads1[] = {
1991    MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1992    MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1993    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1994    // 5134 = 12 + 5 * 1024 + 2
1995    MockRead("Content-Length: 5134\r\n\r\n"),
1996    MockRead(ASYNC, large_body_string.data(), large_body_string.size()),
1997
1998    // Lastly, the server responds with the actual content.
1999    MockRead("HTTP/1.1 200 OK\r\n"),
2000    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2001    MockRead("Content-Length: 5\r\n\r\n"),
2002    MockRead("hello"),
2003  };
2004
2005  // An incorrect reconnect would cause this to be read.
2006  MockRead data_reads2[] = {
2007    MockRead(SYNCHRONOUS, ERR_FAILED),
2008  };
2009
2010  StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2011                                 data_writes1, arraysize(data_writes1));
2012  StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2013                                 NULL, 0);
2014  session_deps_.socket_factory->AddSocketDataProvider(&data1);
2015  session_deps_.socket_factory->AddSocketDataProvider(&data2);
2016
2017  TestCompletionCallback callback1;
2018
2019  scoped_ptr<HttpTransaction> trans(
2020      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2021  int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
2022  EXPECT_EQ(ERR_IO_PENDING, rv);
2023
2024  rv = callback1.WaitForResult();
2025  EXPECT_EQ(OK, rv);
2026
2027  const HttpResponseInfo* response = trans->GetResponseInfo();
2028  ASSERT_TRUE(response != NULL);
2029  EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
2030
2031  TestCompletionCallback callback2;
2032
2033  rv = trans->RestartWithAuth(
2034      AuthCredentials(kFoo, kBar), callback2.callback());
2035  EXPECT_EQ(ERR_IO_PENDING, rv);
2036
2037  rv = callback2.WaitForResult();
2038  EXPECT_EQ(OK, rv);
2039
2040  response = trans->GetResponseInfo();
2041  ASSERT_TRUE(response != NULL);
2042  EXPECT_TRUE(response->auth_challenge.get() == NULL);
2043  EXPECT_EQ(5, response->headers->GetContentLength());
2044}
2045
2046// Test the request-challenge-retry sequence for basic auth, over a keep-alive
2047// connection, but the server gets impatient and closes the connection.
2048TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) {
2049  HttpRequestInfo request;
2050  request.method = "GET";
2051  request.url = GURL("http://www.google.com/");
2052  request.load_flags = 0;
2053
2054  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2055
2056  MockWrite data_writes1[] = {
2057    MockWrite("GET / HTTP/1.1\r\n"
2058              "Host: www.google.com\r\n"
2059              "Connection: keep-alive\r\n\r\n"),
2060    // This simulates the seemingly successful write to a closed connection
2061    // if the bug is not fixed.
2062    MockWrite("GET / HTTP/1.1\r\n"
2063              "Host: www.google.com\r\n"
2064              "Connection: keep-alive\r\n"
2065              "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2066  };
2067
2068  MockRead data_reads1[] = {
2069    MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2070    MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2071    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2072    MockRead("Content-Length: 14\r\n\r\n"),
2073    // Tell MockTCPClientSocket to simulate the server closing the connection.
2074    MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
2075    MockRead("Unauthorized\r\n"),
2076    MockRead(SYNCHRONOUS, OK),  // The server closes the connection.
2077  };
2078
2079  // After calling trans->RestartWithAuth(), this is the request we should
2080  // be issuing -- the final header line contains the credentials.
2081  MockWrite data_writes2[] = {
2082    MockWrite("GET / HTTP/1.1\r\n"
2083              "Host: www.google.com\r\n"
2084              "Connection: keep-alive\r\n"
2085              "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2086  };
2087
2088  // Lastly, the server responds with the actual content.
2089  MockRead data_reads2[] = {
2090    MockRead("HTTP/1.1 200 OK\r\n"),
2091    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2092    MockRead("Content-Length: 5\r\n\r\n"),
2093    MockRead("hello"),
2094  };
2095
2096  StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2097                                 data_writes1, arraysize(data_writes1));
2098  StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2099                                 data_writes2, arraysize(data_writes2));
2100  session_deps_.socket_factory->AddSocketDataProvider(&data1);
2101  session_deps_.socket_factory->AddSocketDataProvider(&data2);
2102
2103  TestCompletionCallback callback1;
2104
2105  scoped_ptr<HttpTransaction> trans(
2106      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2107  int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
2108  EXPECT_EQ(ERR_IO_PENDING, rv);
2109
2110  rv = callback1.WaitForResult();
2111  EXPECT_EQ(OK, rv);
2112
2113  const HttpResponseInfo* response = trans->GetResponseInfo();
2114  ASSERT_TRUE(response != NULL);
2115  EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
2116
2117  TestCompletionCallback callback2;
2118
2119  rv = trans->RestartWithAuth(
2120      AuthCredentials(kFoo, kBar), callback2.callback());
2121  EXPECT_EQ(ERR_IO_PENDING, rv);
2122
2123  rv = callback2.WaitForResult();
2124  EXPECT_EQ(OK, rv);
2125
2126  response = trans->GetResponseInfo();
2127  ASSERT_TRUE(response != NULL);
2128  EXPECT_TRUE(response->auth_challenge.get() == NULL);
2129  EXPECT_EQ(5, response->headers->GetContentLength());
2130}
2131
2132// Test the request-challenge-retry sequence for basic auth, over a connection
2133// that requires a restart when setting up an SSL tunnel.
2134TEST_P(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAlive) {
2135  HttpRequestInfo request;
2136  request.method = "GET";
2137  request.url = GURL("https://www.google.com/");
2138  // when the no authentication data flag is set.
2139  request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
2140
2141  // Configure against proxy server "myproxy:70".
2142  session_deps_.proxy_service.reset(
2143      ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
2144  CapturingBoundNetLog log;
2145  session_deps_.net_log = log.bound().net_log();
2146  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2147
2148  // Since we have proxy, should try to establish tunnel.
2149  MockWrite data_writes1[] = {
2150    MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2151              "Host: www.google.com\r\n"
2152              "Proxy-Connection: keep-alive\r\n\r\n"),
2153
2154    // After calling trans->RestartWithAuth(), this is the request we should
2155    // be issuing -- the final header line contains the credentials.
2156    MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2157              "Host: www.google.com\r\n"
2158              "Proxy-Connection: keep-alive\r\n"
2159              "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2160
2161    MockWrite("GET / HTTP/1.1\r\n"
2162              "Host: www.google.com\r\n"
2163              "Connection: keep-alive\r\n\r\n"),
2164  };
2165
2166  // The proxy responds to the connect with a 407, using a persistent
2167  // connection.
2168  MockRead data_reads1[] = {
2169    // No credentials.
2170    MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2171    MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2172    MockRead("Proxy-Connection: close\r\n\r\n"),
2173
2174    MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2175
2176    MockRead("HTTP/1.1 200 OK\r\n"),
2177    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2178    MockRead("Content-Length: 5\r\n\r\n"),
2179    MockRead(SYNCHRONOUS, "hello"),
2180  };
2181
2182  StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2183                                 data_writes1, arraysize(data_writes1));
2184  session_deps_.socket_factory->AddSocketDataProvider(&data1);
2185  SSLSocketDataProvider ssl(ASYNC, OK);
2186  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2187
2188  TestCompletionCallback callback1;
2189
2190  scoped_ptr<HttpTransaction> trans(
2191      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2192
2193  int rv = trans->Start(&request, callback1.callback(), log.bound());
2194  EXPECT_EQ(ERR_IO_PENDING, rv);
2195
2196  rv = callback1.WaitForResult();
2197  EXPECT_EQ(OK, rv);
2198  net::CapturingNetLog::CapturedEntryList entries;
2199  log.GetEntries(&entries);
2200  size_t pos = ExpectLogContainsSomewhere(
2201      entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
2202      NetLog::PHASE_NONE);
2203  ExpectLogContainsSomewhere(
2204      entries, pos,
2205      NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
2206      NetLog::PHASE_NONE);
2207
2208  const HttpResponseInfo* response = trans->GetResponseInfo();
2209  ASSERT_TRUE(response != NULL);
2210  ASSERT_FALSE(response->headers.get() == NULL);
2211  EXPECT_EQ(407, response->headers->response_code());
2212  EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2213  EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2214
2215  LoadTimingInfo load_timing_info;
2216  // CONNECT requests and responses are handled at the connect job level, so
2217  // the transaction does not yet have a connection.
2218  EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
2219
2220  TestCompletionCallback callback2;
2221
2222  rv = trans->RestartWithAuth(
2223      AuthCredentials(kFoo, kBar), callback2.callback());
2224  EXPECT_EQ(ERR_IO_PENDING, rv);
2225
2226  rv = callback2.WaitForResult();
2227  EXPECT_EQ(OK, rv);
2228
2229  response = trans->GetResponseInfo();
2230  ASSERT_TRUE(response != NULL);
2231
2232  EXPECT_TRUE(response->headers->IsKeepAlive());
2233  EXPECT_EQ(200, response->headers->response_code());
2234  EXPECT_EQ(5, response->headers->GetContentLength());
2235  EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2236
2237  // The password prompt info should not be set.
2238  EXPECT_TRUE(response->auth_challenge.get() == NULL);
2239
2240  EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
2241  TestLoadTimingNotReusedWithPac(load_timing_info,
2242                                 CONNECT_TIMING_HAS_SSL_TIMES);
2243
2244  trans.reset();
2245  session->CloseAllConnections();
2246}
2247
2248// Test the request-challenge-retry sequence for basic auth, over a keep-alive
2249// proxy connection, when setting up an SSL tunnel.
2250TEST_P(HttpNetworkTransactionTest, BasicAuthProxyKeepAlive) {
2251  HttpRequestInfo request;
2252  request.method = "GET";
2253  request.url = GURL("https://www.google.com/");
2254  // Ensure that proxy authentication is attempted even
2255  // when the no authentication data flag is set.
2256  request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
2257
2258  // Configure against proxy server "myproxy:70".
2259  session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
2260  CapturingBoundNetLog log;
2261  session_deps_.net_log = log.bound().net_log();
2262  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2263
2264  scoped_ptr<HttpTransaction> trans(
2265      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2266
2267  // Since we have proxy, should try to establish tunnel.
2268  MockWrite data_writes1[] = {
2269    MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2270              "Host: www.google.com\r\n"
2271              "Proxy-Connection: keep-alive\r\n\r\n"),
2272
2273    // After calling trans->RestartWithAuth(), this is the request we should
2274    // be issuing -- the final header line contains the credentials.
2275    MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2276              "Host: www.google.com\r\n"
2277              "Proxy-Connection: keep-alive\r\n"
2278              "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
2279  };
2280
2281  // The proxy responds to the connect with a 407, using a persistent
2282  // connection.
2283  MockRead data_reads1[] = {
2284    // No credentials.
2285    MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2286    MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2287    MockRead("Content-Length: 10\r\n\r\n"),
2288    MockRead("0123456789"),
2289
2290    // Wrong credentials (wrong password).
2291    MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2292    MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2293    MockRead("Content-Length: 10\r\n\r\n"),
2294    // No response body because the test stops reading here.
2295    MockRead(SYNCHRONOUS, ERR_UNEXPECTED),  // Should not be reached.
2296  };
2297
2298  StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2299                                 data_writes1, arraysize(data_writes1));
2300  session_deps_.socket_factory->AddSocketDataProvider(&data1);
2301
2302  TestCompletionCallback callback1;
2303
2304  int rv = trans->Start(&request, callback1.callback(), log.bound());
2305  EXPECT_EQ(ERR_IO_PENDING, rv);
2306
2307  rv = callback1.WaitForResult();
2308  EXPECT_EQ(OK, rv);
2309  net::CapturingNetLog::CapturedEntryList entries;
2310  log.GetEntries(&entries);
2311  size_t pos = ExpectLogContainsSomewhere(
2312      entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
2313      NetLog::PHASE_NONE);
2314  ExpectLogContainsSomewhere(
2315      entries, pos,
2316      NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
2317      NetLog::PHASE_NONE);
2318
2319  const HttpResponseInfo* response = trans->GetResponseInfo();
2320  ASSERT_TRUE(response != NULL);
2321  ASSERT_FALSE(response->headers.get() == NULL);
2322  EXPECT_TRUE(response->headers->IsKeepAlive());
2323  EXPECT_EQ(407, response->headers->response_code());
2324  EXPECT_EQ(10, response->headers->GetContentLength());
2325  EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2326  EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2327
2328  TestCompletionCallback callback2;
2329
2330  // Wrong password (should be "bar").
2331  rv = trans->RestartWithAuth(
2332      AuthCredentials(kFoo, kBaz), callback2.callback());
2333  EXPECT_EQ(ERR_IO_PENDING, rv);
2334
2335  rv = callback2.WaitForResult();
2336  EXPECT_EQ(OK, rv);
2337
2338  response = trans->GetResponseInfo();
2339  ASSERT_TRUE(response != NULL);
2340  ASSERT_FALSE(response->headers.get() == NULL);
2341  EXPECT_TRUE(response->headers->IsKeepAlive());
2342  EXPECT_EQ(407, response->headers->response_code());
2343  EXPECT_EQ(10, response->headers->GetContentLength());
2344  EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2345  EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2346
2347  // Flush the idle socket before the NetLog and HttpNetworkTransaction go
2348  // out of scope.
2349  session->CloseAllConnections();
2350}
2351
2352// Test that we don't read the response body when we fail to establish a tunnel,
2353// even if the user cancels the proxy's auth attempt.
2354TEST_P(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
2355  HttpRequestInfo request;
2356  request.method = "GET";
2357  request.url = GURL("https://www.google.com/");
2358  request.load_flags = 0;
2359
2360  // Configure against proxy server "myproxy:70".
2361  session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
2362
2363  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2364
2365  scoped_ptr<HttpTransaction> trans(
2366      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2367
2368  // Since we have proxy, should try to establish tunnel.
2369  MockWrite data_writes[] = {
2370    MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2371              "Host: www.google.com\r\n"
2372              "Proxy-Connection: keep-alive\r\n\r\n"),
2373  };
2374
2375  // The proxy responds to the connect with a 407.
2376  MockRead data_reads[] = {
2377    MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2378    MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2379    MockRead("Content-Length: 10\r\n\r\n"),
2380    MockRead(SYNCHRONOUS, ERR_UNEXPECTED),  // Should not be reached.
2381  };
2382
2383  StaticSocketDataProvider data(data_reads, arraysize(data_reads),
2384                                data_writes, arraysize(data_writes));
2385  session_deps_.socket_factory->AddSocketDataProvider(&data);
2386
2387  TestCompletionCallback callback;
2388
2389  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
2390  EXPECT_EQ(ERR_IO_PENDING, rv);
2391
2392  rv = callback.WaitForResult();
2393  EXPECT_EQ(OK, rv);
2394
2395  const HttpResponseInfo* response = trans->GetResponseInfo();
2396  ASSERT_TRUE(response != NULL);
2397
2398  EXPECT_TRUE(response->headers->IsKeepAlive());
2399  EXPECT_EQ(407, response->headers->response_code());
2400  EXPECT_EQ(10, response->headers->GetContentLength());
2401  EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2402
2403  std::string response_data;
2404  rv = ReadTransaction(trans.get(), &response_data);
2405  EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
2406
2407  // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
2408  session->CloseAllConnections();
2409}
2410
2411// Test when a server (non-proxy) returns a 407 (proxy-authenticate).
2412// The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
2413TEST_P(HttpNetworkTransactionTest, UnexpectedProxyAuth) {
2414  HttpRequestInfo request;
2415  request.method = "GET";
2416  request.url = GURL("http://www.google.com/");
2417  request.load_flags = 0;
2418
2419  // We are using a DIRECT connection (i.e. no proxy) for this session.
2420  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2421  scoped_ptr<HttpTransaction> trans(
2422      new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
2423
2424  MockWrite data_writes1[] = {
2425    MockWrite("GET / HTTP/1.1\r\n"
2426              "Host: www.google.com\r\n"
2427              "Connection: keep-alive\r\n\r\n"),
2428  };
2429
2430  MockRead data_reads1[] = {
2431    MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
2432    MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2433    // Large content-length -- won't matter, as connection will be reset.
2434    MockRead("Content-Length: 10000\r\n\r\n"),
2435    MockRead(SYNCHRONOUS, ERR_FAILED),
2436  };
2437
2438  StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2439                                 data_writes1, arraysize(data_writes1));
2440  session_deps_.socket_factory->AddSocketDataProvider(&data1);
2441
2442  TestCompletionCallback callback;
2443
2444  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
2445  EXPECT_EQ(ERR_IO_PENDING, rv);
2446
2447  rv = callback.WaitForResult();
2448  EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
2449}
2450
2451// Tests when an HTTPS server (non-proxy) returns a 407 (proxy-authentication)
2452// through a non-authenticating proxy. The request should fail with
2453// ERR_UNEXPECTED_PROXY_AUTH.
2454// Note that it is impossible to detect if an HTTP server returns a 407 through
2455// a non-authenticating proxy - there is nothing to indicate whether the
2456// response came from the proxy or the server, so it is treated as if the proxy
2457// issued the challenge.
2458TEST_P(HttpNetworkTransactionTest,
2459       HttpsServerRequestsProxyAuthThroughProxy) {
2460  HttpRequestInfo request;
2461  request.method = "GET";
2462  request.url = GURL("https://www.google.com/");
2463
2464  session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
2465  CapturingBoundNetLog log;
2466  session_deps_.net_log = log.bound().net_log();
2467  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2468
2469  // Since we have proxy, should try to establish tunnel.
2470  MockWrite data_writes1[] = {
2471    MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2472              "Host: www.google.com\r\n"
2473              "Proxy-Connection: keep-alive\r\n\r\n"),
2474
2475    MockWrite("GET / HTTP/1.1\r\n"
2476              "Host: www.google.com\r\n"
2477              "Connection: keep-alive\r\n\r\n"),
2478  };
2479
2480  MockRead data_reads1[] = {
2481    MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2482
2483    MockRead("HTTP/1.1 407 Unauthorized\r\n"),
2484    MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2485    MockRead("\r\n"),
2486    MockRead(SYNCHRONOUS, OK),
2487  };
2488
2489  StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2490                                 data_writes1, arraysize(data_writes1));
2491  session_deps_.socket_factory->AddSocketDataProvider(&data1);
2492  SSLSocketDataProvider ssl(ASYNC, OK);
2493  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2494
2495  TestCompletionCallback callback1;
2496
2497  scoped_ptr<HttpTransaction> trans(
2498      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2499
2500  int rv = trans->Start(&request, callback1.callback(), log.bound());
2501  EXPECT_EQ(ERR_IO_PENDING, rv);
2502
2503  rv = callback1.WaitForResult();
2504  EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
2505  net::CapturingNetLog::CapturedEntryList entries;
2506  log.GetEntries(&entries);
2507  size_t pos = ExpectLogContainsSomewhere(
2508      entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
2509      NetLog::PHASE_NONE);
2510  ExpectLogContainsSomewhere(
2511      entries, pos,
2512      NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
2513      NetLog::PHASE_NONE);
2514}
2515
2516// Test the load timing for HTTPS requests with an HTTP proxy.
2517TEST_P(HttpNetworkTransactionTest, HttpProxyLoadTimingNoPacTwoRequests) {
2518  HttpRequestInfo request1;
2519  request1.method = "GET";
2520  request1.url = GURL("https://www.google.com/1");
2521
2522  HttpRequestInfo request2;
2523  request2.method = "GET";
2524  request2.url = GURL("https://www.google.com/2");
2525
2526  // Configure against proxy server "myproxy:70".
2527  session_deps_.proxy_service.reset(
2528      ProxyService::CreateFixed("PROXY myproxy:70"));
2529  CapturingBoundNetLog log;
2530  session_deps_.net_log = log.bound().net_log();
2531  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2532
2533  // Since we have proxy, should try to establish tunnel.
2534  MockWrite data_writes1[] = {
2535    MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2536              "Host: www.google.com\r\n"
2537              "Proxy-Connection: keep-alive\r\n\r\n"),
2538
2539    MockWrite("GET /1 HTTP/1.1\r\n"
2540              "Host: www.google.com\r\n"
2541              "Connection: keep-alive\r\n\r\n"),
2542
2543    MockWrite("GET /2 HTTP/1.1\r\n"
2544              "Host: www.google.com\r\n"
2545              "Connection: keep-alive\r\n\r\n"),
2546  };
2547
2548  // The proxy responds to the connect with a 407, using a persistent
2549  // connection.
2550  MockRead data_reads1[] = {
2551    MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2552
2553    MockRead("HTTP/1.1 200 OK\r\n"),
2554    MockRead("Content-Length: 1\r\n\r\n"),
2555    MockRead(SYNCHRONOUS, "1"),
2556
2557    MockRead("HTTP/1.1 200 OK\r\n"),
2558    MockRead("Content-Length: 2\r\n\r\n"),
2559    MockRead(SYNCHRONOUS, "22"),
2560  };
2561
2562  StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2563                                 data_writes1, arraysize(data_writes1));
2564  session_deps_.socket_factory->AddSocketDataProvider(&data1);
2565  SSLSocketDataProvider ssl(ASYNC, OK);
2566  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2567
2568  TestCompletionCallback callback1;
2569  scoped_ptr<HttpTransaction> trans1(
2570      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2571
2572  int rv = trans1->Start(&request1, callback1.callback(), log.bound());
2573  EXPECT_EQ(ERR_IO_PENDING, rv);
2574
2575  rv = callback1.WaitForResult();
2576  EXPECT_EQ(OK, rv);
2577
2578  const HttpResponseInfo* response1 = trans1->GetResponseInfo();
2579  ASSERT_TRUE(response1 != NULL);
2580  ASSERT_TRUE(response1->headers.get() != NULL);
2581  EXPECT_EQ(1, response1->headers->GetContentLength());
2582
2583  LoadTimingInfo load_timing_info1;
2584  EXPECT_TRUE(trans1->GetLoadTimingInfo(&load_timing_info1));
2585  TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_SSL_TIMES);
2586
2587  trans1.reset();
2588
2589  TestCompletionCallback callback2;
2590  scoped_ptr<HttpTransaction> trans2(
2591      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2592
2593  rv = trans2->Start(&request2, callback2.callback(), log.bound());
2594  EXPECT_EQ(ERR_IO_PENDING, rv);
2595
2596  rv = callback2.WaitForResult();
2597  EXPECT_EQ(OK, rv);
2598
2599  const HttpResponseInfo* response2 = trans2->GetResponseInfo();
2600  ASSERT_TRUE(response2 != NULL);
2601  ASSERT_TRUE(response2->headers.get() != NULL);
2602  EXPECT_EQ(2, response2->headers->GetContentLength());
2603
2604  LoadTimingInfo load_timing_info2;
2605  EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
2606  TestLoadTimingReused(load_timing_info2);
2607
2608  EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
2609
2610  trans2.reset();
2611  session->CloseAllConnections();
2612}
2613
2614// Test the load timing for HTTPS requests with an HTTP proxy and a PAC script.
2615TEST_P(HttpNetworkTransactionTest, HttpProxyLoadTimingWithPacTwoRequests) {
2616  HttpRequestInfo request1;
2617  request1.method = "GET";
2618  request1.url = GURL("https://www.google.com/1");
2619
2620  HttpRequestInfo request2;
2621  request2.method = "GET";
2622  request2.url = GURL("https://www.google.com/2");
2623
2624  // Configure against proxy server "myproxy:70".
2625  session_deps_.proxy_service.reset(
2626      ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
2627  CapturingBoundNetLog log;
2628  session_deps_.net_log = log.bound().net_log();
2629  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2630
2631  // Since we have proxy, should try to establish tunnel.
2632  MockWrite data_writes1[] = {
2633    MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2634              "Host: www.google.com\r\n"
2635              "Proxy-Connection: keep-alive\r\n\r\n"),
2636
2637    MockWrite("GET /1 HTTP/1.1\r\n"
2638              "Host: www.google.com\r\n"
2639              "Connection: keep-alive\r\n\r\n"),
2640
2641    MockWrite("GET /2 HTTP/1.1\r\n"
2642              "Host: www.google.com\r\n"
2643              "Connection: keep-alive\r\n\r\n"),
2644  };
2645
2646  // The proxy responds to the connect with a 407, using a persistent
2647  // connection.
2648  MockRead data_reads1[] = {
2649    MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2650
2651    MockRead("HTTP/1.1 200 OK\r\n"),
2652    MockRead("Content-Length: 1\r\n\r\n"),
2653    MockRead(SYNCHRONOUS, "1"),
2654
2655    MockRead("HTTP/1.1 200 OK\r\n"),
2656    MockRead("Content-Length: 2\r\n\r\n"),
2657    MockRead(SYNCHRONOUS, "22"),
2658  };
2659
2660  StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2661                                 data_writes1, arraysize(data_writes1));
2662  session_deps_.socket_factory->AddSocketDataProvider(&data1);
2663  SSLSocketDataProvider ssl(ASYNC, OK);
2664  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2665
2666  TestCompletionCallback callback1;
2667  scoped_ptr<HttpTransaction> trans1(
2668      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2669
2670  int rv = trans1->Start(&request1, callback1.callback(), log.bound());
2671  EXPECT_EQ(ERR_IO_PENDING, rv);
2672
2673  rv = callback1.WaitForResult();
2674  EXPECT_EQ(OK, rv);
2675
2676  const HttpResponseInfo* response1 = trans1->GetResponseInfo();
2677  ASSERT_TRUE(response1 != NULL);
2678  ASSERT_TRUE(response1->headers.get() != NULL);
2679  EXPECT_EQ(1, response1->headers->GetContentLength());
2680
2681  LoadTimingInfo load_timing_info1;
2682  EXPECT_TRUE(trans1->GetLoadTimingInfo(&load_timing_info1));
2683  TestLoadTimingNotReusedWithPac(load_timing_info1,
2684                                 CONNECT_TIMING_HAS_SSL_TIMES);
2685
2686  trans1.reset();
2687
2688  TestCompletionCallback callback2;
2689  scoped_ptr<HttpTransaction> trans2(
2690      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2691
2692  rv = trans2->Start(&request2, callback2.callback(), log.bound());
2693  EXPECT_EQ(ERR_IO_PENDING, rv);
2694
2695  rv = callback2.WaitForResult();
2696  EXPECT_EQ(OK, rv);
2697
2698  const HttpResponseInfo* response2 = trans2->GetResponseInfo();
2699  ASSERT_TRUE(response2 != NULL);
2700  ASSERT_TRUE(response2->headers.get() != NULL);
2701  EXPECT_EQ(2, response2->headers->GetContentLength());
2702
2703  LoadTimingInfo load_timing_info2;
2704  EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
2705  TestLoadTimingReusedWithPac(load_timing_info2);
2706
2707  EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
2708
2709  trans2.reset();
2710  session->CloseAllConnections();
2711}
2712
2713// Test a simple get through an HTTPS Proxy.
2714TEST_P(HttpNetworkTransactionTest, HttpsProxyGet) {
2715  HttpRequestInfo request;
2716  request.method = "GET";
2717  request.url = GURL("http://www.google.com/");
2718
2719  // Configure against https proxy server "proxy:70".
2720  session_deps_.proxy_service.reset(ProxyService::CreateFixed(
2721      "https://proxy:70"));
2722  CapturingBoundNetLog log;
2723  session_deps_.net_log = log.bound().net_log();
2724  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2725
2726  // Since we have proxy, should use full url
2727  MockWrite data_writes1[] = {
2728    MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2729              "Host: www.google.com\r\n"
2730              "Proxy-Connection: keep-alive\r\n\r\n"),
2731  };
2732
2733  MockRead data_reads1[] = {
2734    MockRead("HTTP/1.1 200 OK\r\n"),
2735    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2736    MockRead("Content-Length: 100\r\n\r\n"),
2737    MockRead(SYNCHRONOUS, OK),
2738  };
2739
2740  StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2741                                 data_writes1, arraysize(data_writes1));
2742  session_deps_.socket_factory->AddSocketDataProvider(&data1);
2743  SSLSocketDataProvider ssl(ASYNC, OK);
2744  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2745
2746  TestCompletionCallback callback1;
2747
2748  scoped_ptr<HttpTransaction> trans(
2749      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2750
2751  int rv = trans->Start(&request, callback1.callback(), log.bound());
2752  EXPECT_EQ(ERR_IO_PENDING, rv);
2753
2754  rv = callback1.WaitForResult();
2755  EXPECT_EQ(OK, rv);
2756
2757  LoadTimingInfo load_timing_info;
2758  EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
2759  TestLoadTimingNotReused(load_timing_info,
2760                          CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
2761
2762  const HttpResponseInfo* response = trans->GetResponseInfo();
2763  ASSERT_TRUE(response != NULL);
2764
2765  EXPECT_TRUE(response->headers->IsKeepAlive());
2766  EXPECT_EQ(200, response->headers->response_code());
2767  EXPECT_EQ(100, response->headers->GetContentLength());
2768  EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2769
2770  // The password prompt info should not be set.
2771  EXPECT_TRUE(response->auth_challenge.get() == NULL);
2772}
2773
2774// Test a SPDY get through an HTTPS Proxy.
2775TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGet) {
2776  HttpRequestInfo request;
2777  request.method = "GET";
2778  request.url = GURL("http://www.google.com/");
2779  request.load_flags = 0;
2780
2781  // Configure against https proxy server "proxy:70".
2782  session_deps_.proxy_service.reset(ProxyService::CreateFixed(
2783      "https://proxy:70"));
2784  CapturingBoundNetLog log;
2785  session_deps_.net_log = log.bound().net_log();
2786  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2787
2788  // fetch http://www.google.com/ via SPDY
2789  scoped_ptr<SpdyFrame> req(
2790      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
2791  MockWrite spdy_writes[] = { CreateMockWrite(*req) };
2792
2793  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2794  scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
2795  MockRead spdy_reads[] = {
2796    CreateMockRead(*resp),
2797    CreateMockRead(*data),
2798    MockRead(ASYNC, 0, 0),
2799  };
2800
2801  DelayedSocketData spdy_data(
2802      1,  // wait for one write to finish before reading.
2803      spdy_reads, arraysize(spdy_reads),
2804      spdy_writes, arraysize(spdy_writes));
2805  session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
2806
2807  SSLSocketDataProvider ssl(ASYNC, OK);
2808  ssl.SetNextProto(GetParam());
2809  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2810
2811  TestCompletionCallback callback1;
2812
2813  scoped_ptr<HttpTransaction> trans(
2814      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2815
2816  int rv = trans->Start(&request, callback1.callback(), log.bound());
2817  EXPECT_EQ(ERR_IO_PENDING, rv);
2818
2819  rv = callback1.WaitForResult();
2820  EXPECT_EQ(OK, rv);
2821
2822  LoadTimingInfo load_timing_info;
2823  EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
2824  TestLoadTimingNotReused(load_timing_info,
2825                          CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
2826
2827  const HttpResponseInfo* response = trans->GetResponseInfo();
2828  ASSERT_TRUE(response != NULL);
2829  ASSERT_TRUE(response->headers.get() != NULL);
2830  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2831
2832  std::string response_data;
2833  ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
2834  EXPECT_EQ(kUploadData, response_data);
2835}
2836
2837// Test a SPDY get through an HTTPS Proxy.
2838TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGetWithProxyAuth) {
2839  HttpRequestInfo request;
2840  request.method = "GET";
2841  request.url = GURL("http://www.google.com/");
2842  request.load_flags = 0;
2843
2844  // Configure against https proxy server "myproxy:70".
2845  session_deps_.proxy_service.reset(
2846      ProxyService::CreateFixed("https://myproxy:70"));
2847  CapturingBoundNetLog log;
2848  session_deps_.net_log = log.bound().net_log();
2849  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2850
2851  // The first request will be a bare GET, the second request will be a
2852  // GET with a Proxy-Authorization header.
2853  scoped_ptr<SpdyFrame> req_get(
2854      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
2855  const char* const kExtraAuthorizationHeaders[] = {
2856    "proxy-authorization", "Basic Zm9vOmJhcg=="
2857  };
2858  scoped_ptr<SpdyFrame> req_get_authorization(
2859      spdy_util_.ConstructSpdyGet(kExtraAuthorizationHeaders,
2860                                  arraysize(kExtraAuthorizationHeaders) / 2,
2861                                  false,
2862                                  3,
2863                                  LOWEST,
2864                                  false));
2865  MockWrite spdy_writes[] = {
2866    CreateMockWrite(*req_get, 1),
2867    CreateMockWrite(*req_get_authorization, 4),
2868  };
2869
2870  // The first response is a 407 proxy authentication challenge, and the second
2871  // response will be a 200 response since the second request includes a valid
2872  // Authorization header.
2873  const char* const kExtraAuthenticationHeaders[] = {
2874    "proxy-authenticate", "Basic realm=\"MyRealm1\""
2875  };
2876  scoped_ptr<SpdyFrame> resp_authentication(
2877      spdy_util_.ConstructSpdySynReplyError(
2878          "407 Proxy Authentication Required",
2879          kExtraAuthenticationHeaders, arraysize(kExtraAuthenticationHeaders)/2,
2880          1));
2881  scoped_ptr<SpdyFrame> body_authentication(
2882      spdy_util_.ConstructSpdyBodyFrame(1, true));
2883  scoped_ptr<SpdyFrame> resp_data(
2884      spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
2885  scoped_ptr<SpdyFrame> body_data(spdy_util_.ConstructSpdyBodyFrame(3, true));
2886  MockRead spdy_reads[] = {
2887    CreateMockRead(*resp_authentication, 2),
2888    CreateMockRead(*body_authentication, 3),
2889    CreateMockRead(*resp_data, 5),
2890    CreateMockRead(*body_data, 6),
2891    MockRead(ASYNC, 0, 7),
2892  };
2893
2894  OrderedSocketData data(
2895      spdy_reads, arraysize(spdy_reads),
2896      spdy_writes, arraysize(spdy_writes));
2897  session_deps_.socket_factory->AddSocketDataProvider(&data);
2898
2899  SSLSocketDataProvider ssl(ASYNC, OK);
2900  ssl.SetNextProto(GetParam());
2901  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2902
2903  TestCompletionCallback callback1;
2904
2905  scoped_ptr<HttpTransaction> trans(
2906      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2907
2908  int rv = trans->Start(&request, callback1.callback(), log.bound());
2909  EXPECT_EQ(ERR_IO_PENDING, rv);
2910
2911  rv = callback1.WaitForResult();
2912  EXPECT_EQ(OK, rv);
2913
2914  const HttpResponseInfo* const response = trans->GetResponseInfo();
2915
2916  ASSERT_TRUE(response != NULL);
2917  ASSERT_TRUE(response->headers.get() != NULL);
2918  EXPECT_EQ(407, response->headers->response_code());
2919  EXPECT_TRUE(response->was_fetched_via_spdy);
2920  EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2921
2922  TestCompletionCallback callback2;
2923
2924  rv = trans->RestartWithAuth(
2925      AuthCredentials(kFoo, kBar), callback2.callback());
2926  EXPECT_EQ(ERR_IO_PENDING, rv);
2927
2928  rv = callback2.WaitForResult();
2929  EXPECT_EQ(OK, rv);
2930
2931  const HttpResponseInfo* const response_restart = trans->GetResponseInfo();
2932
2933  ASSERT_TRUE(response_restart != NULL);
2934  ASSERT_TRUE(response_restart->headers.get() != NULL);
2935  EXPECT_EQ(200, response_restart->headers->response_code());
2936  // The password prompt info should not be set.
2937  EXPECT_TRUE(response_restart->auth_challenge.get() == NULL);
2938}
2939
2940// Test a SPDY CONNECT through an HTTPS Proxy to an HTTPS (non-SPDY) Server.
2941TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectHttps) {
2942  HttpRequestInfo request;
2943  request.method = "GET";
2944  request.url = GURL("https://www.google.com/");
2945  request.load_flags = 0;
2946
2947  // Configure against https proxy server "proxy:70".
2948  session_deps_.proxy_service.reset(ProxyService::CreateFixed(
2949      "https://proxy:70"));
2950  CapturingBoundNetLog log;
2951  session_deps_.net_log = log.bound().net_log();
2952  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2953
2954  scoped_ptr<HttpTransaction> trans(
2955      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2956
2957  // CONNECT to www.google.com:443 via SPDY
2958  scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(NULL, 0, 1,
2959                                                                LOWEST));
2960  // fetch https://www.google.com/ via HTTP
2961
2962  const char get[] = "GET / HTTP/1.1\r\n"
2963    "Host: www.google.com\r\n"
2964    "Connection: keep-alive\r\n\r\n";
2965  scoped_ptr<SpdyFrame> wrapped_get(
2966      spdy_util_.ConstructSpdyBodyFrame(1, get, strlen(get), false));
2967  scoped_ptr<SpdyFrame> conn_resp(
2968      spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2969  const char resp[] = "HTTP/1.1 200 OK\r\n"
2970      "Content-Length: 10\r\n\r\n";
2971  scoped_ptr<SpdyFrame> wrapped_get_resp(
2972      spdy_util_.ConstructSpdyBodyFrame(1, resp, strlen(resp), false));
2973  scoped_ptr<SpdyFrame> wrapped_body(
2974      spdy_util_.ConstructSpdyBodyFrame(1, "1234567890", 10, false));
2975  scoped_ptr<SpdyFrame> window_update(
2976      spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp->size()));
2977
2978  MockWrite spdy_writes[] = {
2979      CreateMockWrite(*connect, 1),
2980      CreateMockWrite(*wrapped_get, 3),
2981      CreateMockWrite(*window_update, 5),
2982  };
2983
2984  MockRead spdy_reads[] = {
2985    CreateMockRead(*conn_resp, 2, ASYNC),
2986    CreateMockRead(*wrapped_get_resp, 4, ASYNC),
2987    CreateMockRead(*wrapped_body, 6, ASYNC),
2988    CreateMockRead(*wrapped_body, 7, ASYNC),
2989    MockRead(ASYNC, 0, 8),
2990  };
2991
2992  OrderedSocketData spdy_data(
2993      spdy_reads, arraysize(spdy_reads),
2994      spdy_writes, arraysize(spdy_writes));
2995  session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
2996
2997  SSLSocketDataProvider ssl(ASYNC, OK);
2998  ssl.SetNextProto(GetParam());
2999  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3000  SSLSocketDataProvider ssl2(ASYNC, OK);
3001  ssl2.was_npn_negotiated = false;
3002  ssl2.protocol_negotiated = kProtoUnknown;
3003  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
3004
3005  TestCompletionCallback callback1;
3006
3007  int rv = trans->Start(&request, callback1.callback(), log.bound());
3008  EXPECT_EQ(ERR_IO_PENDING, rv);
3009
3010  rv = callback1.WaitForResult();
3011  EXPECT_EQ(OK, rv);
3012
3013  LoadTimingInfo load_timing_info;
3014  EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3015  TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
3016
3017  const HttpResponseInfo* response = trans->GetResponseInfo();
3018  ASSERT_TRUE(response != NULL);
3019  ASSERT_TRUE(response->headers.get() != NULL);
3020  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3021
3022  std::string response_data;
3023  ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
3024  EXPECT_EQ("1234567890", response_data);
3025}
3026
3027// Test a SPDY CONNECT through an HTTPS Proxy to a SPDY server.
3028TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectSpdy) {
3029  HttpRequestInfo request;
3030  request.method = "GET";
3031  request.url = GURL("https://www.google.com/");
3032  request.load_flags = 0;
3033
3034  // Configure against https proxy server "proxy:70".
3035  session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3036      "https://proxy:70"));
3037  CapturingBoundNetLog log;
3038  session_deps_.net_log = log.bound().net_log();
3039  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3040
3041  scoped_ptr<HttpTransaction> trans(
3042      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3043
3044  // CONNECT to www.google.com:443 via SPDY
3045  scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(NULL, 0, 1,
3046                                                                LOWEST));
3047  // fetch https://www.google.com/ via SPDY
3048  const char* const kMyUrl = "https://www.google.com/";
3049  scoped_ptr<SpdyFrame> get(
3050      spdy_util_.ConstructSpdyGet(kMyUrl, false, 1, LOWEST));
3051  scoped_ptr<SpdyFrame> wrapped_get(
3052      spdy_util_.ConstructWrappedSpdyFrame(get, 1));
3053  scoped_ptr<SpdyFrame> conn_resp(
3054      spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3055  scoped_ptr<SpdyFrame> get_resp(
3056      spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3057  scoped_ptr<SpdyFrame> wrapped_get_resp(
3058      spdy_util_.ConstructWrappedSpdyFrame(get_resp, 1));
3059  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
3060  scoped_ptr<SpdyFrame> wrapped_body(
3061      spdy_util_.ConstructWrappedSpdyFrame(body, 1));
3062  scoped_ptr<SpdyFrame> window_update_get_resp(
3063      spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp->size()));
3064  scoped_ptr<SpdyFrame> window_update_body(
3065      spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_body->size()));
3066
3067  MockWrite spdy_writes[] = {
3068      CreateMockWrite(*connect, 1),
3069      CreateMockWrite(*wrapped_get, 3),
3070      CreateMockWrite(*window_update_get_resp, 5),
3071      CreateMockWrite(*window_update_body, 7),
3072  };
3073
3074  MockRead spdy_reads[] = {
3075    CreateMockRead(*conn_resp, 2, ASYNC),
3076    CreateMockRead(*wrapped_get_resp, 4, ASYNC),
3077    CreateMockRead(*wrapped_body, 6, ASYNC),
3078    MockRead(ASYNC, 0, 8),
3079  };
3080
3081  OrderedSocketData spdy_data(
3082      spdy_reads, arraysize(spdy_reads),
3083      spdy_writes, arraysize(spdy_writes));
3084  session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
3085
3086  SSLSocketDataProvider ssl(ASYNC, OK);
3087  ssl.SetNextProto(GetParam());
3088  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3089  SSLSocketDataProvider ssl2(ASYNC, OK);
3090  ssl2.SetNextProto(GetParam());
3091  ssl2.protocol_negotiated = GetParam();
3092  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
3093
3094  TestCompletionCallback callback1;
3095
3096  int rv = trans->Start(&request, callback1.callback(), log.bound());
3097  EXPECT_EQ(ERR_IO_PENDING, rv);
3098
3099  rv = callback1.WaitForResult();
3100  EXPECT_EQ(OK, rv);
3101
3102  LoadTimingInfo load_timing_info;
3103  EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3104  TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
3105
3106  const HttpResponseInfo* response = trans->GetResponseInfo();
3107  ASSERT_TRUE(response != NULL);
3108  ASSERT_TRUE(response->headers.get() != NULL);
3109  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3110
3111  std::string response_data;
3112  ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
3113  EXPECT_EQ(kUploadData, response_data);
3114}
3115
3116// Test a SPDY CONNECT failure through an HTTPS Proxy.
3117TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectFailure) {
3118  HttpRequestInfo request;
3119  request.method = "GET";
3120  request.url = GURL("https://www.google.com/");
3121  request.load_flags = 0;
3122
3123  // Configure against https proxy server "proxy:70".
3124  session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3125      "https://proxy:70"));
3126  CapturingBoundNetLog log;
3127  session_deps_.net_log = log.bound().net_log();
3128  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3129
3130  scoped_ptr<HttpTransaction> trans(
3131      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3132
3133  // CONNECT to www.google.com:443 via SPDY
3134  scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(NULL, 0, 1,
3135                                                                LOWEST));
3136  scoped_ptr<SpdyFrame> get(
3137      spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
3138
3139  MockWrite spdy_writes[] = {
3140      CreateMockWrite(*connect, 1),
3141      CreateMockWrite(*get, 3),
3142  };
3143
3144  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdySynReplyError(1));
3145  scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
3146  MockRead spdy_reads[] = {
3147    CreateMockRead(*resp, 2, ASYNC),
3148    MockRead(ASYNC, 0, 4),
3149  };
3150
3151  OrderedSocketData spdy_data(
3152      spdy_reads, arraysize(spdy_reads),
3153      spdy_writes, arraysize(spdy_writes));
3154  session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
3155
3156  SSLSocketDataProvider ssl(ASYNC, OK);
3157  ssl.SetNextProto(GetParam());
3158  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3159  SSLSocketDataProvider ssl2(ASYNC, OK);
3160  ssl2.SetNextProto(GetParam());
3161  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
3162
3163  TestCompletionCallback callback1;
3164
3165  int rv = trans->Start(&request, callback1.callback(), log.bound());
3166  EXPECT_EQ(ERR_IO_PENDING, rv);
3167
3168  rv = callback1.WaitForResult();
3169  EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
3170
3171  // TODO(ttuttle): Anything else to check here?
3172}
3173
3174// Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
3175// HTTPS Proxy to different servers.
3176TEST_P(HttpNetworkTransactionTest,
3177       HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsTwoServers) {
3178  // Configure against https proxy server "proxy:70".
3179  session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3180      "https://proxy:70"));
3181  CapturingBoundNetLog log;
3182  session_deps_.net_log = log.bound().net_log();
3183  scoped_refptr<HttpNetworkSession> session(
3184      SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
3185
3186  HttpRequestInfo request1;
3187  request1.method = "GET";
3188  request1.url = GURL("https://www.google.com/");
3189  request1.load_flags = 0;
3190
3191  HttpRequestInfo request2;
3192  request2.method = "GET";
3193  request2.url = GURL("https://news.google.com/");
3194  request2.load_flags = 0;
3195
3196  // CONNECT to www.google.com:443 via SPDY.
3197  scoped_ptr<SpdyFrame> connect1(spdy_util_.ConstructSpdyConnect(NULL, 0, 1,
3198                                                                 LOWEST));
3199  scoped_ptr<SpdyFrame> conn_resp1(
3200      spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3201
3202  // Fetch https://www.google.com/ via HTTP.
3203  const char get1[] = "GET / HTTP/1.1\r\n"
3204      "Host: www.google.com\r\n"
3205      "Connection: keep-alive\r\n\r\n";
3206  scoped_ptr<SpdyFrame> wrapped_get1(
3207      spdy_util_.ConstructSpdyBodyFrame(1, get1, strlen(get1), false));
3208  const char resp1[] = "HTTP/1.1 200 OK\r\n"
3209      "Content-Length: 1\r\n\r\n";
3210  scoped_ptr<SpdyFrame> wrapped_get_resp1(
3211      spdy_util_.ConstructSpdyBodyFrame(1, resp1, strlen(resp1), false));
3212  scoped_ptr<SpdyFrame> wrapped_body1(
3213      spdy_util_.ConstructSpdyBodyFrame(1, "1", 1, false));
3214  scoped_ptr<SpdyFrame> window_update(
3215      spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp1->size()));
3216
3217  // CONNECT to news.google.com:443 via SPDY.
3218  const char* const kConnectHeaders2[] = {
3219    spdy_util_.GetMethodKey(), "CONNECT",
3220    spdy_util_.GetPathKey(), "news.google.com:443",
3221    spdy_util_.GetHostKey(), "news.google.com",
3222    spdy_util_.GetVersionKey(), "HTTP/1.1",
3223  };
3224  scoped_ptr<SpdyFrame> connect2(
3225      spdy_util_.ConstructSpdyControlFrame(NULL,
3226                                           0,
3227                                           /*compressed*/ false,
3228                                           3,
3229                                           LOWEST,
3230                                           SYN_STREAM,
3231                                           CONTROL_FLAG_NONE,
3232                                           kConnectHeaders2,
3233                                           arraysize(kConnectHeaders2),
3234                                           0));
3235  scoped_ptr<SpdyFrame> conn_resp2(
3236      spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
3237
3238  // Fetch https://news.google.com/ via HTTP.
3239  const char get2[] = "GET / HTTP/1.1\r\n"
3240      "Host: news.google.com\r\n"
3241      "Connection: keep-alive\r\n\r\n";
3242  scoped_ptr<SpdyFrame> wrapped_get2(
3243      spdy_util_.ConstructSpdyBodyFrame(3, get2, strlen(get2), false));
3244  const char resp2[] = "HTTP/1.1 200 OK\r\n"
3245      "Content-Length: 2\r\n\r\n";
3246  scoped_ptr<SpdyFrame> wrapped_get_resp2(
3247      spdy_util_.ConstructSpdyBodyFrame(3, resp2, strlen(resp2), false));
3248  scoped_ptr<SpdyFrame> wrapped_body2(
3249      spdy_util_.ConstructSpdyBodyFrame(3, "22", 2, false));
3250
3251  MockWrite spdy_writes[] = {
3252      CreateMockWrite(*connect1, 0),
3253      CreateMockWrite(*wrapped_get1, 2),
3254      CreateMockWrite(*connect2, 5),
3255      CreateMockWrite(*wrapped_get2, 7),
3256  };
3257
3258  MockRead spdy_reads[] = {
3259    CreateMockRead(*conn_resp1, 1, ASYNC),
3260    CreateMockRead(*wrapped_get_resp1, 3, ASYNC),
3261    CreateMockRead(*wrapped_body1, 4, ASYNC),
3262    CreateMockRead(*conn_resp2, 6, ASYNC),
3263    CreateMockRead(*wrapped_get_resp2, 8, ASYNC),
3264    CreateMockRead(*wrapped_body2, 9, ASYNC),
3265    MockRead(ASYNC, 0, 10),
3266  };
3267
3268  DeterministicSocketData spdy_data(
3269      spdy_reads, arraysize(spdy_reads),
3270      spdy_writes, arraysize(spdy_writes));
3271  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&spdy_data);
3272
3273  SSLSocketDataProvider ssl(ASYNC, OK);
3274  ssl.SetNextProto(GetParam());
3275  session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
3276  SSLSocketDataProvider ssl2(ASYNC, OK);
3277  ssl2.was_npn_negotiated = false;
3278  ssl2.protocol_negotiated = kProtoUnknown;
3279  session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2);
3280  SSLSocketDataProvider ssl3(ASYNC, OK);
3281  ssl3.was_npn_negotiated = false;
3282  ssl3.protocol_negotiated = kProtoUnknown;
3283  session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl3);
3284
3285  TestCompletionCallback callback;
3286
3287  scoped_ptr<HttpTransaction> trans(
3288      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3289  int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
3290  EXPECT_EQ(ERR_IO_PENDING, rv);
3291  // The first connect and request, each of their responses, and the body.
3292  spdy_data.RunFor(5);
3293
3294  rv = callback.WaitForResult();
3295  EXPECT_EQ(OK, rv);
3296
3297  LoadTimingInfo load_timing_info;
3298  EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3299  TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
3300
3301  const HttpResponseInfo* response = trans->GetResponseInfo();
3302  ASSERT_TRUE(response != NULL);
3303  ASSERT_TRUE(response->headers.get() != NULL);
3304  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3305
3306  std::string response_data;
3307  scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(256));
3308  EXPECT_EQ(1, trans->Read(buf.get(), 256, callback.callback()));
3309
3310  scoped_ptr<HttpTransaction> trans2(
3311      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3312  rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
3313  EXPECT_EQ(ERR_IO_PENDING, rv);
3314
3315  // The second connect and request, each of their responses, and the body.
3316  spdy_data.RunFor(5);
3317  rv = callback.WaitForResult();
3318  EXPECT_EQ(OK, rv);
3319
3320  LoadTimingInfo load_timing_info2;
3321  EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
3322  // Even though the SPDY connection is reused, a new tunnelled connection has
3323  // to be created, so the socket's load timing looks like a fresh connection.
3324  TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_SSL_TIMES);
3325
3326  // The requests should have different IDs, since they each are using their own
3327  // separate stream.
3328  EXPECT_NE(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
3329
3330  EXPECT_EQ(2, trans2->Read(buf.get(), 256, callback.callback()));
3331}
3332
3333// Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
3334// HTTPS Proxy to the same server.
3335TEST_P(HttpNetworkTransactionTest,
3336       HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsSameServer) {
3337  // Configure against https proxy server "proxy:70".
3338  session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3339      "https://proxy:70"));
3340  CapturingBoundNetLog log;
3341  session_deps_.net_log = log.bound().net_log();
3342  scoped_refptr<HttpNetworkSession> session(
3343      SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
3344
3345  HttpRequestInfo request1;
3346  request1.method = "GET";
3347  request1.url = GURL("https://www.google.com/");
3348  request1.load_flags = 0;
3349
3350  HttpRequestInfo request2;
3351  request2.method = "GET";
3352  request2.url = GURL("https://www.google.com/2");
3353  request2.load_flags = 0;
3354
3355  // CONNECT to www.google.com:443 via SPDY.
3356  scoped_ptr<SpdyFrame> connect1(spdy_util_.ConstructSpdyConnect(NULL, 0, 1,
3357                                                                 LOWEST));
3358  scoped_ptr<SpdyFrame> conn_resp1(
3359      spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3360
3361  // Fetch https://www.google.com/ via HTTP.
3362  const char get1[] = "GET / HTTP/1.1\r\n"
3363      "Host: www.google.com\r\n"
3364      "Connection: keep-alive\r\n\r\n";
3365  scoped_ptr<SpdyFrame> wrapped_get1(
3366      spdy_util_.ConstructSpdyBodyFrame(1, get1, strlen(get1), false));
3367  const char resp1[] = "HTTP/1.1 200 OK\r\n"
3368      "Content-Length: 1\r\n\r\n";
3369  scoped_ptr<SpdyFrame> wrapped_get_resp1(
3370      spdy_util_.ConstructSpdyBodyFrame(1, resp1, strlen(resp1), false));
3371  scoped_ptr<SpdyFrame> wrapped_body1(
3372      spdy_util_.ConstructSpdyBodyFrame(1, "1", 1, false));
3373  scoped_ptr<SpdyFrame> window_update(
3374      spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp1->size()));
3375
3376  // Fetch https://www.google.com/2 via HTTP.
3377  const char get2[] = "GET /2 HTTP/1.1\r\n"
3378      "Host: www.google.com\r\n"
3379      "Connection: keep-alive\r\n\r\n";
3380  scoped_ptr<SpdyFrame> wrapped_get2(
3381      spdy_util_.ConstructSpdyBodyFrame(1, get2, strlen(get2), false));
3382  const char resp2[] = "HTTP/1.1 200 OK\r\n"
3383      "Content-Length: 2\r\n\r\n";
3384  scoped_ptr<SpdyFrame> wrapped_get_resp2(
3385      spdy_util_.ConstructSpdyBodyFrame(1, resp2, strlen(resp2), false));
3386  scoped_ptr<SpdyFrame> wrapped_body2(
3387      spdy_util_.ConstructSpdyBodyFrame(1, "22", 2, false));
3388
3389  MockWrite spdy_writes[] = {
3390      CreateMockWrite(*connect1, 0),
3391      CreateMockWrite(*wrapped_get1, 2),
3392      CreateMockWrite(*wrapped_get2, 5),
3393  };
3394
3395  MockRead spdy_reads[] = {
3396    CreateMockRead(*conn_resp1, 1, ASYNC),
3397    CreateMockRead(*wrapped_get_resp1, 3, ASYNC),
3398    CreateMockRead(*wrapped_body1, 4, ASYNC),
3399    CreateMockRead(*wrapped_get_resp2, 6, ASYNC),
3400    CreateMockRead(*wrapped_body2, 7, ASYNC),
3401    MockRead(ASYNC, 0, 8),
3402  };
3403
3404  DeterministicSocketData spdy_data(
3405      spdy_reads, arraysize(spdy_reads),
3406      spdy_writes, arraysize(spdy_writes));
3407  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&spdy_data);
3408
3409  SSLSocketDataProvider ssl(ASYNC, OK);
3410  ssl.SetNextProto(GetParam());
3411  session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
3412  SSLSocketDataProvider ssl2(ASYNC, OK);
3413  ssl2.was_npn_negotiated = false;
3414  ssl2.protocol_negotiated = kProtoUnknown;
3415  session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2);
3416
3417  TestCompletionCallback callback;
3418
3419  scoped_ptr<HttpTransaction> trans(
3420      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3421  int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
3422  EXPECT_EQ(ERR_IO_PENDING, rv);
3423  // The first connect and request, each of their responses, and the body.
3424  spdy_data.RunFor(5);
3425
3426  rv = callback.WaitForResult();
3427  EXPECT_EQ(OK, rv);
3428
3429  LoadTimingInfo load_timing_info;
3430  EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3431  TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
3432
3433  const HttpResponseInfo* response = trans->GetResponseInfo();
3434  ASSERT_TRUE(response != NULL);
3435  ASSERT_TRUE(response->headers.get() != NULL);
3436  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3437
3438  std::string response_data;
3439  scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(256));
3440  EXPECT_EQ(1, trans->Read(buf.get(), 256, callback.callback()));
3441  trans.reset();
3442
3443  scoped_ptr<HttpTransaction> trans2(
3444      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3445  rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
3446  EXPECT_EQ(ERR_IO_PENDING, rv);
3447
3448  // The second request, response, and body.  There should not be a second
3449  // connect.
3450  spdy_data.RunFor(3);
3451  rv = callback.WaitForResult();
3452  EXPECT_EQ(OK, rv);
3453
3454  LoadTimingInfo load_timing_info2;
3455  EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
3456  TestLoadTimingReused(load_timing_info2);
3457
3458  // The requests should have the same ID.
3459  EXPECT_EQ(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
3460
3461  EXPECT_EQ(2, trans2->Read(buf.get(), 256, callback.callback()));
3462}
3463
3464// Test load timing in the case of of two HTTP requests through a SPDY HTTPS
3465// Proxy to different servers.
3466TEST_P(HttpNetworkTransactionTest,
3467       HttpsProxySpdyLoadTimingTwoHttpRequests) {
3468  // Configure against https proxy server "proxy:70".
3469  session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3470      "https://proxy:70"));
3471  CapturingBoundNetLog log;
3472  session_deps_.net_log = log.bound().net_log();
3473  scoped_refptr<HttpNetworkSession> session(
3474      SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
3475
3476  HttpRequestInfo request1;
3477  request1.method = "GET";
3478  request1.url = GURL("http://www.google.com/");
3479  request1.load_flags = 0;
3480
3481  HttpRequestInfo request2;
3482  request2.method = "GET";
3483  request2.url = GURL("http://news.google.com/");
3484  request2.load_flags = 0;
3485
3486  // http://www.google.com/
3487  scoped_ptr<SpdyHeaderBlock> headers(
3488      spdy_util_.ConstructGetHeaderBlockForProxy("http://www.google.com/"));
3489  scoped_ptr<SpdyFrame> get1(spdy_util_.ConstructSpdyControlFrame(
3490      headers.Pass(), false, 1, LOWEST, SYN_STREAM, CONTROL_FLAG_FIN, 0));
3491  scoped_ptr<SpdyFrame> get_resp1(
3492      spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3493  scoped_ptr<SpdyFrame> body1(
3494      spdy_util_.ConstructSpdyBodyFrame(1, "1", 1, true));
3495
3496  // http://news.google.com/
3497  scoped_ptr<SpdyHeaderBlock> headers2(
3498      spdy_util_.ConstructGetHeaderBlockForProxy("http://news.google.com/"));
3499  scoped_ptr<SpdyFrame> get2(spdy_util_.ConstructSpdyControlFrame(
3500      headers2.Pass(), false, 3, LOWEST, SYN_STREAM, CONTROL_FLAG_FIN, 0));
3501  scoped_ptr<SpdyFrame> get_resp2(
3502      spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
3503  scoped_ptr<SpdyFrame> body2(
3504      spdy_util_.ConstructSpdyBodyFrame(3, "22", 2, true));
3505
3506  MockWrite spdy_writes[] = {
3507      CreateMockWrite(*get1, 0),
3508      CreateMockWrite(*get2, 3),
3509  };
3510
3511  MockRead spdy_reads[] = {
3512    CreateMockRead(*get_resp1, 1, ASYNC),
3513    CreateMockRead(*body1, 2, ASYNC),
3514    CreateMockRead(*get_resp2, 4, ASYNC),
3515    CreateMockRead(*body2, 5, ASYNC),
3516    MockRead(ASYNC, 0, 6),
3517  };
3518
3519  DeterministicSocketData spdy_data(
3520      spdy_reads, arraysize(spdy_reads),
3521      spdy_writes, arraysize(spdy_writes));
3522  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&spdy_data);
3523
3524  SSLSocketDataProvider ssl(ASYNC, OK);
3525  ssl.SetNextProto(GetParam());
3526  session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
3527
3528  TestCompletionCallback callback;
3529
3530  scoped_ptr<HttpTransaction> trans(
3531      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3532  int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
3533  EXPECT_EQ(ERR_IO_PENDING, rv);
3534  spdy_data.RunFor(2);
3535
3536  rv = callback.WaitForResult();
3537  EXPECT_EQ(OK, rv);
3538
3539  LoadTimingInfo load_timing_info;
3540  EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3541  TestLoadTimingNotReused(load_timing_info,
3542                          CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
3543
3544  const HttpResponseInfo* response = trans->GetResponseInfo();
3545  ASSERT_TRUE(response != NULL);
3546  ASSERT_TRUE(response->headers.get() != NULL);
3547  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3548
3549  std::string response_data;
3550  scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(256));
3551  EXPECT_EQ(ERR_IO_PENDING, trans->Read(buf.get(), 256, callback.callback()));
3552  spdy_data.RunFor(1);
3553  EXPECT_EQ(1, callback.WaitForResult());
3554  // Delete the first request, so the second one can reuse the socket.
3555  trans.reset();
3556
3557  scoped_ptr<HttpTransaction> trans2(
3558      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3559  rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
3560  EXPECT_EQ(ERR_IO_PENDING, rv);
3561
3562  spdy_data.RunFor(2);
3563  rv = callback.WaitForResult();
3564  EXPECT_EQ(OK, rv);
3565
3566  LoadTimingInfo load_timing_info2;
3567  EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
3568  TestLoadTimingReused(load_timing_info2);
3569
3570  // The requests should have the same ID.
3571  EXPECT_EQ(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
3572
3573  EXPECT_EQ(ERR_IO_PENDING, trans2->Read(buf.get(), 256, callback.callback()));
3574  spdy_data.RunFor(1);
3575  EXPECT_EQ(2, callback.WaitForResult());
3576}
3577
3578// Test the challenge-response-retry sequence through an HTTPS Proxy
3579TEST_P(HttpNetworkTransactionTest, HttpsProxyAuthRetry) {
3580  HttpRequestInfo request;
3581  request.method = "GET";
3582  request.url = GURL("http://www.google.com/");
3583  // when the no authentication data flag is set.
3584  request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
3585
3586  // Configure against https proxy server "myproxy:70".
3587  session_deps_.proxy_service.reset(
3588      ProxyService::CreateFixed("https://myproxy:70"));
3589  CapturingBoundNetLog log;
3590  session_deps_.net_log = log.bound().net_log();
3591  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3592
3593  // Since we have proxy, should use full url
3594  MockWrite data_writes1[] = {
3595    MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
3596              "Host: www.google.com\r\n"
3597              "Proxy-Connection: keep-alive\r\n\r\n"),
3598
3599    // After calling trans->RestartWithAuth(), this is the request we should
3600    // be issuing -- the final header line contains the credentials.
3601    MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
3602              "Host: www.google.com\r\n"
3603              "Proxy-Connection: keep-alive\r\n"
3604              "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3605  };
3606
3607  // The proxy responds to the GET with a 407, using a persistent
3608  // connection.
3609  MockRead data_reads1[] = {
3610    // No credentials.
3611    MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3612    MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3613    MockRead("Proxy-Connection: keep-alive\r\n"),
3614    MockRead("Content-Length: 0\r\n\r\n"),
3615
3616    MockRead("HTTP/1.1 200 OK\r\n"),
3617    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3618    MockRead("Content-Length: 100\r\n\r\n"),
3619    MockRead(SYNCHRONOUS, OK),
3620  };
3621
3622  StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3623                                 data_writes1, arraysize(data_writes1));
3624  session_deps_.socket_factory->AddSocketDataProvider(&data1);
3625  SSLSocketDataProvider ssl(ASYNC, OK);
3626  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3627
3628  TestCompletionCallback callback1;
3629
3630  scoped_ptr<HttpTransaction> trans(
3631      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3632
3633  int rv = trans->Start(&request, callback1.callback(), log.bound());
3634  EXPECT_EQ(ERR_IO_PENDING, rv);
3635
3636  rv = callback1.WaitForResult();
3637  EXPECT_EQ(OK, rv);
3638
3639  LoadTimingInfo load_timing_info;
3640  EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3641  TestLoadTimingNotReused(load_timing_info,
3642                          CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
3643
3644  const HttpResponseInfo* response = trans->GetResponseInfo();
3645  ASSERT_TRUE(response != NULL);
3646  ASSERT_FALSE(response->headers.get() == NULL);
3647  EXPECT_EQ(407, response->headers->response_code());
3648  EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3649  EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
3650
3651  TestCompletionCallback callback2;
3652
3653  rv = trans->RestartWithAuth(
3654      AuthCredentials(kFoo, kBar), callback2.callback());
3655  EXPECT_EQ(ERR_IO_PENDING, rv);
3656
3657  rv = callback2.WaitForResult();
3658  EXPECT_EQ(OK, rv);
3659
3660  load_timing_info = LoadTimingInfo();
3661  EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3662  // Retrying with HTTP AUTH is considered to be reusing a socket.
3663  TestLoadTimingReused(load_timing_info);
3664
3665  response = trans->GetResponseInfo();
3666  ASSERT_TRUE(response != NULL);
3667
3668  EXPECT_TRUE(response->headers->IsKeepAlive());
3669  EXPECT_EQ(200, response->headers->response_code());
3670  EXPECT_EQ(100, response->headers->GetContentLength());
3671  EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3672
3673  // The password prompt info should not be set.
3674  EXPECT_TRUE(response->auth_challenge.get() == NULL);
3675}
3676
3677void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
3678    const MockRead& status, int expected_status) {
3679  HttpRequestInfo request;
3680  request.method = "GET";
3681  request.url = GURL("https://www.google.com/");
3682  request.load_flags = 0;
3683
3684  // Configure against proxy server "myproxy:70".
3685  session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
3686  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3687
3688  // Since we have proxy, should try to establish tunnel.
3689  MockWrite data_writes[] = {
3690    MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
3691              "Host: www.google.com\r\n"
3692              "Proxy-Connection: keep-alive\r\n\r\n"),
3693  };
3694
3695  MockRead data_reads[] = {
3696    status,
3697    MockRead("Content-Length: 10\r\n\r\n"),
3698    // No response body because the test stops reading here.
3699    MockRead(SYNCHRONOUS, ERR_UNEXPECTED),  // Should not be reached.
3700  };
3701
3702  StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3703                                data_writes, arraysize(data_writes));
3704  session_deps_.socket_factory->AddSocketDataProvider(&data);
3705
3706  TestCompletionCallback callback;
3707
3708  scoped_ptr<HttpTransaction> trans(
3709      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3710
3711  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
3712  EXPECT_EQ(ERR_IO_PENDING, rv);
3713
3714  rv = callback.WaitForResult();
3715  EXPECT_EQ(expected_status, rv);
3716}
3717
3718void HttpNetworkTransactionTest::ConnectStatusHelper(
3719    const MockRead& status) {
3720  ConnectStatusHelperWithExpectedStatus(
3721      status, ERR_TUNNEL_CONNECTION_FAILED);
3722}
3723
3724TEST_P(HttpNetworkTransactionTest, ConnectStatus100) {
3725  ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
3726}
3727
3728TEST_P(HttpNetworkTransactionTest, ConnectStatus101) {
3729  ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
3730}
3731
3732TEST_P(HttpNetworkTransactionTest, ConnectStatus201) {
3733  ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
3734}
3735
3736TEST_P(HttpNetworkTransactionTest, ConnectStatus202) {
3737  ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
3738}
3739
3740TEST_P(HttpNetworkTransactionTest, ConnectStatus203) {
3741  ConnectStatusHelper(
3742      MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
3743}
3744
3745TEST_P(HttpNetworkTransactionTest, ConnectStatus204) {
3746  ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
3747}
3748
3749TEST_P(HttpNetworkTransactionTest, ConnectStatus205) {
3750  ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
3751}
3752
3753TEST_P(HttpNetworkTransactionTest, ConnectStatus206) {
3754  ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
3755}
3756
3757TEST_P(HttpNetworkTransactionTest, ConnectStatus300) {
3758  ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
3759}
3760
3761TEST_P(HttpNetworkTransactionTest, ConnectStatus301) {
3762  ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
3763}
3764
3765TEST_P(HttpNetworkTransactionTest, ConnectStatus302) {
3766  ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
3767}
3768
3769TEST_P(HttpNetworkTransactionTest, ConnectStatus303) {
3770  ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
3771}
3772
3773TEST_P(HttpNetworkTransactionTest, ConnectStatus304) {
3774  ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
3775}
3776
3777TEST_P(HttpNetworkTransactionTest, ConnectStatus305) {
3778  ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
3779}
3780
3781TEST_P(HttpNetworkTransactionTest, ConnectStatus306) {
3782  ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
3783}
3784
3785TEST_P(HttpNetworkTransactionTest, ConnectStatus307) {
3786  ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
3787}
3788
3789TEST_P(HttpNetworkTransactionTest, ConnectStatus400) {
3790  ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
3791}
3792
3793TEST_P(HttpNetworkTransactionTest, ConnectStatus401) {
3794  ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
3795}
3796
3797TEST_P(HttpNetworkTransactionTest, ConnectStatus402) {
3798  ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
3799}
3800
3801TEST_P(HttpNetworkTransactionTest, ConnectStatus403) {
3802  ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
3803}
3804
3805TEST_P(HttpNetworkTransactionTest, ConnectStatus404) {
3806  ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
3807}
3808
3809TEST_P(HttpNetworkTransactionTest, ConnectStatus405) {
3810  ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
3811}
3812
3813TEST_P(HttpNetworkTransactionTest, ConnectStatus406) {
3814  ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
3815}
3816
3817TEST_P(HttpNetworkTransactionTest, ConnectStatus407) {
3818  ConnectStatusHelperWithExpectedStatus(
3819      MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3820      ERR_PROXY_AUTH_UNSUPPORTED);
3821}
3822
3823TEST_P(HttpNetworkTransactionTest, ConnectStatus408) {
3824  ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
3825}
3826
3827TEST_P(HttpNetworkTransactionTest, ConnectStatus409) {
3828  ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
3829}
3830
3831TEST_P(HttpNetworkTransactionTest, ConnectStatus410) {
3832  ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
3833}
3834
3835TEST_P(HttpNetworkTransactionTest, ConnectStatus411) {
3836  ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
3837}
3838
3839TEST_P(HttpNetworkTransactionTest, ConnectStatus412) {
3840  ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
3841}
3842
3843TEST_P(HttpNetworkTransactionTest, ConnectStatus413) {
3844  ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
3845}
3846
3847TEST_P(HttpNetworkTransactionTest, ConnectStatus414) {
3848  ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
3849}
3850
3851TEST_P(HttpNetworkTransactionTest, ConnectStatus415) {
3852  ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
3853}
3854
3855TEST_P(HttpNetworkTransactionTest, ConnectStatus416) {
3856  ConnectStatusHelper(
3857      MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
3858}
3859
3860TEST_P(HttpNetworkTransactionTest, ConnectStatus417) {
3861  ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
3862}
3863
3864TEST_P(HttpNetworkTransactionTest, ConnectStatus500) {
3865  ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
3866}
3867
3868TEST_P(HttpNetworkTransactionTest, ConnectStatus501) {
3869  ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
3870}
3871
3872TEST_P(HttpNetworkTransactionTest, ConnectStatus502) {
3873  ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
3874}
3875
3876TEST_P(HttpNetworkTransactionTest, ConnectStatus503) {
3877  ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
3878}
3879
3880TEST_P(HttpNetworkTransactionTest, ConnectStatus504) {
3881  ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
3882}
3883
3884TEST_P(HttpNetworkTransactionTest, ConnectStatus505) {
3885  ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
3886}
3887
3888// Test the flow when both the proxy server AND origin server require
3889// authentication. Again, this uses basic auth for both since that is
3890// the simplest to mock.
3891TEST_P(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
3892  HttpRequestInfo request;
3893  request.method = "GET";
3894  request.url = GURL("http://www.google.com/");
3895  request.load_flags = 0;
3896
3897  // Configure against proxy server "myproxy:70".
3898  session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
3899  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3900
3901  scoped_ptr<HttpTransaction> trans(
3902      new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
3903
3904  MockWrite data_writes1[] = {
3905    MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
3906              "Host: www.google.com\r\n"
3907              "Proxy-Connection: keep-alive\r\n\r\n"),
3908  };
3909
3910  MockRead data_reads1[] = {
3911    MockRead("HTTP/1.0 407 Unauthorized\r\n"),
3912    // Give a couple authenticate options (only the middle one is actually
3913    // supported).
3914    MockRead("Proxy-Authenticate: Basic invalid\r\n"),  // Malformed.
3915    MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3916    MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
3917    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3918    // Large content-length -- won't matter, as connection will be reset.
3919    MockRead("Content-Length: 10000\r\n\r\n"),
3920    MockRead(SYNCHRONOUS, ERR_FAILED),
3921  };
3922
3923  // After calling trans->RestartWithAuth() the first time, this is the
3924  // request we should be issuing -- the final header line contains the
3925  // proxy's credentials.
3926  MockWrite data_writes2[] = {
3927    MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
3928              "Host: www.google.com\r\n"
3929              "Proxy-Connection: keep-alive\r\n"
3930              "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3931  };
3932
3933  // Now the proxy server lets the request pass through to origin server.
3934  // The origin server responds with a 401.
3935  MockRead data_reads2[] = {
3936    MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3937    // Note: We are using the same realm-name as the proxy server. This is
3938    // completely valid, as realms are unique across hosts.
3939    MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3940    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3941    MockRead("Content-Length: 2000\r\n\r\n"),
3942    MockRead(SYNCHRONOUS, ERR_FAILED),  // Won't be reached.
3943  };
3944
3945  // After calling trans->RestartWithAuth() the second time, we should send
3946  // the credentials for both the proxy and origin server.
3947  MockWrite data_writes3[] = {
3948    MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
3949              "Host: www.google.com\r\n"
3950              "Proxy-Connection: keep-alive\r\n"
3951              "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
3952              "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
3953  };
3954
3955  // Lastly we get the desired content.
3956  MockRead data_reads3[] = {
3957    MockRead("HTTP/1.0 200 OK\r\n"),
3958    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3959    MockRead("Content-Length: 100\r\n\r\n"),
3960    MockRead(SYNCHRONOUS, OK),
3961  };
3962
3963  StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3964                                 data_writes1, arraysize(data_writes1));
3965  StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3966                                 data_writes2, arraysize(data_writes2));
3967  StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
3968                                 data_writes3, arraysize(data_writes3));
3969  session_deps_.socket_factory->AddSocketDataProvider(&data1);
3970  session_deps_.socket_factory->AddSocketDataProvider(&data2);
3971  session_deps_.socket_factory->AddSocketDataProvider(&data3);
3972
3973  TestCompletionCallback callback1;
3974
3975  int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
3976  EXPECT_EQ(ERR_IO_PENDING, rv);
3977
3978  rv = callback1.WaitForResult();
3979  EXPECT_EQ(OK, rv);
3980
3981  const HttpResponseInfo* response = trans->GetResponseInfo();
3982  ASSERT_TRUE(response != NULL);
3983  EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
3984
3985  TestCompletionCallback callback2;
3986
3987  rv = trans->RestartWithAuth(
3988      AuthCredentials(kFoo, kBar), callback2.callback());
3989  EXPECT_EQ(ERR_IO_PENDING, rv);
3990
3991  rv = callback2.WaitForResult();
3992  EXPECT_EQ(OK, rv);
3993
3994  response = trans->GetResponseInfo();
3995  ASSERT_TRUE(response != NULL);
3996  EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
3997
3998  TestCompletionCallback callback3;
3999
4000  rv = trans->RestartWithAuth(
4001      AuthCredentials(kFoo2, kBar2), callback3.callback());
4002  EXPECT_EQ(ERR_IO_PENDING, rv);
4003
4004  rv = callback3.WaitForResult();
4005  EXPECT_EQ(OK, rv);
4006
4007  response = trans->GetResponseInfo();
4008  EXPECT_TRUE(response->auth_challenge.get() == NULL);
4009  EXPECT_EQ(100, response->headers->GetContentLength());
4010}
4011
4012// For the NTLM implementation using SSPI, we skip the NTLM tests since we
4013// can't hook into its internals to cause it to generate predictable NTLM
4014// authorization headers.
4015#if defined(NTLM_PORTABLE)
4016// The NTLM authentication unit tests were generated by capturing the HTTP
4017// requests and responses using Fiddler 2 and inspecting the generated random
4018// bytes in the debugger.
4019
4020// Enter the correct password and authenticate successfully.
4021TEST_P(HttpNetworkTransactionTest, NTLMAuth1) {
4022  HttpRequestInfo request;
4023  request.method = "GET";
4024  request.url = GURL("http://172.22.68.17/kids/login.aspx");
4025
4026  // Ensure load is not disrupted by flags which suppress behaviour specific
4027  // to other auth schemes.
4028  request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
4029
4030  HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom1,
4031                                                    MockGetHostName);
4032  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4033
4034  MockWrite data_writes1[] = {
4035    MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4036              "Host: 172.22.68.17\r\n"
4037              "Connection: keep-alive\r\n\r\n"),
4038  };
4039
4040  MockRead data_reads1[] = {
4041    MockRead("HTTP/1.1 401 Access Denied\r\n"),
4042    // Negotiate and NTLM are often requested together.  However, we only want
4043    // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
4044    // the header that requests Negotiate for this test.
4045    MockRead("WWW-Authenticate: NTLM\r\n"),
4046    MockRead("Connection: close\r\n"),
4047    MockRead("Content-Length: 42\r\n"),
4048    MockRead("Content-Type: text/html\r\n\r\n"),
4049    // Missing content -- won't matter, as connection will be reset.
4050    MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
4051  };
4052
4053  MockWrite data_writes2[] = {
4054    // After restarting with a null identity, this is the
4055    // request we should be issuing -- the final header line contains a Type
4056    // 1 message.
4057    MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4058              "Host: 172.22.68.17\r\n"
4059              "Connection: keep-alive\r\n"
4060              "Authorization: NTLM "
4061              "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4062
4063    // After calling trans->RestartWithAuth(), we should send a Type 3 message
4064    // (the credentials for the origin server).  The second request continues
4065    // on the same connection.
4066    MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4067              "Host: 172.22.68.17\r\n"
4068              "Connection: keep-alive\r\n"
4069              "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4070              "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4071              "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
4072              "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
4073              "ahlhx5I=\r\n\r\n"),
4074  };
4075
4076  MockRead data_reads2[] = {
4077    // The origin server responds with a Type 2 message.
4078    MockRead("HTTP/1.1 401 Access Denied\r\n"),
4079    MockRead("WWW-Authenticate: NTLM "
4080             "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
4081             "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4082             "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4083             "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4084             "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4085             "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4086             "BtAAAAAAA=\r\n"),
4087    MockRead("Content-Length: 42\r\n"),
4088    MockRead("Content-Type: text/html\r\n\r\n"),
4089    MockRead("You are not authorized to view this page\r\n"),
4090
4091    // Lastly we get the desired content.
4092    MockRead("HTTP/1.1 200 OK\r\n"),
4093    MockRead("Content-Type: text/html; charset=utf-8\r\n"),
4094    MockRead("Content-Length: 13\r\n\r\n"),
4095    MockRead("Please Login\r\n"),
4096    MockRead(SYNCHRONOUS, OK),
4097  };
4098
4099  StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4100                                 data_writes1, arraysize(data_writes1));
4101  StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4102                                 data_writes2, arraysize(data_writes2));
4103  session_deps_.socket_factory->AddSocketDataProvider(&data1);
4104  session_deps_.socket_factory->AddSocketDataProvider(&data2);
4105
4106  TestCompletionCallback callback1;
4107
4108  scoped_ptr<HttpTransaction> trans(
4109      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4110
4111  int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
4112  EXPECT_EQ(ERR_IO_PENDING, rv);
4113
4114  rv = callback1.WaitForResult();
4115  EXPECT_EQ(OK, rv);
4116
4117  EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4118
4119  const HttpResponseInfo* response = trans->GetResponseInfo();
4120  ASSERT_FALSE(response == NULL);
4121  EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
4122
4123  TestCompletionCallback callback2;
4124
4125  rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kTestingNTLM),
4126                              callback2.callback());
4127  EXPECT_EQ(ERR_IO_PENDING, rv);
4128
4129  rv = callback2.WaitForResult();
4130  EXPECT_EQ(OK, rv);
4131
4132  EXPECT_TRUE(trans->IsReadyToRestartForAuth());
4133
4134  response = trans->GetResponseInfo();
4135  ASSERT_TRUE(response != NULL);
4136  EXPECT_TRUE(response->auth_challenge.get() == NULL);
4137
4138  TestCompletionCallback callback3;
4139
4140  rv = trans->RestartWithAuth(AuthCredentials(), callback3.callback());
4141  EXPECT_EQ(ERR_IO_PENDING, rv);
4142
4143  rv = callback3.WaitForResult();
4144  EXPECT_EQ(OK, rv);
4145
4146  response = trans->GetResponseInfo();
4147  ASSERT_TRUE(response != NULL);
4148  EXPECT_TRUE(response->auth_challenge.get() == NULL);
4149  EXPECT_EQ(13, response->headers->GetContentLength());
4150}
4151
4152// Enter a wrong password, and then the correct one.
4153TEST_P(HttpNetworkTransactionTest, NTLMAuth2) {
4154  HttpRequestInfo request;
4155  request.method = "GET";
4156  request.url = GURL("http://172.22.68.17/kids/login.aspx");
4157  request.load_flags = 0;
4158
4159  HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom2,
4160                                                    MockGetHostName);
4161  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4162
4163  MockWrite data_writes1[] = {
4164    MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4165              "Host: 172.22.68.17\r\n"
4166              "Connection: keep-alive\r\n\r\n"),
4167  };
4168
4169  MockRead data_reads1[] = {
4170    MockRead("HTTP/1.1 401 Access Denied\r\n"),
4171    // Negotiate and NTLM are often requested together.  However, we only want
4172    // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
4173    // the header that requests Negotiate for this test.
4174    MockRead("WWW-Authenticate: NTLM\r\n"),
4175    MockRead("Connection: close\r\n"),
4176    MockRead("Content-Length: 42\r\n"),
4177    MockRead("Content-Type: text/html\r\n\r\n"),
4178    // Missing content -- won't matter, as connection will be reset.
4179    MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
4180  };
4181
4182  MockWrite data_writes2[] = {
4183    // After restarting with a null identity, this is the
4184    // request we should be issuing -- the final header line contains a Type
4185    // 1 message.
4186    MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4187              "Host: 172.22.68.17\r\n"
4188              "Connection: keep-alive\r\n"
4189              "Authorization: NTLM "
4190              "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4191
4192    // After calling trans->RestartWithAuth(), we should send a Type 3 message
4193    // (the credentials for the origin server).  The second request continues
4194    // on the same connection.
4195    MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4196              "Host: 172.22.68.17\r\n"
4197              "Connection: keep-alive\r\n"
4198              "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4199              "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4200              "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
4201              "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
4202              "4Ww7b7E=\r\n\r\n"),
4203  };
4204
4205  MockRead data_reads2[] = {
4206    // The origin server responds with a Type 2 message.
4207    MockRead("HTTP/1.1 401 Access Denied\r\n"),
4208    MockRead("WWW-Authenticate: NTLM "
4209             "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
4210             "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4211             "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4212             "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4213             "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4214             "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4215             "BtAAAAAAA=\r\n"),
4216    MockRead("Content-Length: 42\r\n"),
4217    MockRead("Content-Type: text/html\r\n\r\n"),
4218    MockRead("You are not authorized to view this page\r\n"),
4219
4220    // Wrong password.
4221    MockRead("HTTP/1.1 401 Access Denied\r\n"),
4222    MockRead("WWW-Authenticate: NTLM\r\n"),
4223    MockRead("Connection: close\r\n"),
4224    MockRead("Content-Length: 42\r\n"),
4225    MockRead("Content-Type: text/html\r\n\r\n"),
4226    // Missing content -- won't matter, as connection will be reset.
4227    MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
4228  };
4229
4230  MockWrite data_writes3[] = {
4231    // After restarting with a null identity, this is the
4232    // request we should be issuing -- the final header line contains a Type
4233    // 1 message.
4234    MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4235              "Host: 172.22.68.17\r\n"
4236              "Connection: keep-alive\r\n"
4237              "Authorization: NTLM "
4238              "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4239
4240    // After calling trans->RestartWithAuth(), we should send a Type 3 message
4241    // (the credentials for the origin server).  The second request continues
4242    // on the same connection.
4243    MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4244              "Host: 172.22.68.17\r\n"
4245              "Connection: keep-alive\r\n"
4246              "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4247              "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4248              "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
4249              "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
4250              "+4MUm7c=\r\n\r\n"),
4251  };
4252
4253  MockRead data_reads3[] = {
4254    // The origin server responds with a Type 2 message.
4255    MockRead("HTTP/1.1 401 Access Denied\r\n"),
4256    MockRead("WWW-Authenticate: NTLM "
4257             "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
4258             "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4259             "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4260             "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4261             "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4262             "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4263             "BtAAAAAAA=\r\n"),
4264    MockRead("Content-Length: 42\r\n"),
4265    MockRead("Content-Type: text/html\r\n\r\n"),
4266    MockRead("You are not authorized to view this page\r\n"),
4267
4268    // Lastly we get the desired content.
4269    MockRead("HTTP/1.1 200 OK\r\n"),
4270    MockRead("Content-Type: text/html; charset=utf-8\r\n"),
4271    MockRead("Content-Length: 13\r\n\r\n"),
4272    MockRead("Please Login\r\n"),
4273    MockRead(SYNCHRONOUS, OK),
4274  };
4275
4276  StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4277                                 data_writes1, arraysize(data_writes1));
4278  StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4279                                 data_writes2, arraysize(data_writes2));
4280  StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
4281                                 data_writes3, arraysize(data_writes3));
4282  session_deps_.socket_factory->AddSocketDataProvider(&data1);
4283  session_deps_.socket_factory->AddSocketDataProvider(&data2);
4284  session_deps_.socket_factory->AddSocketDataProvider(&data3);
4285
4286  TestCompletionCallback callback1;
4287
4288  scoped_ptr<HttpTransaction> trans(
4289      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4290
4291  int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
4292  EXPECT_EQ(ERR_IO_PENDING, rv);
4293
4294  rv = callback1.WaitForResult();
4295  EXPECT_EQ(OK, rv);
4296
4297  EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4298
4299  const HttpResponseInfo* response = trans->GetResponseInfo();
4300  ASSERT_TRUE(response != NULL);
4301  EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
4302
4303  TestCompletionCallback callback2;
4304
4305  // Enter the wrong password.
4306  rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kWrongPassword),
4307                              callback2.callback());
4308  EXPECT_EQ(ERR_IO_PENDING, rv);
4309
4310  rv = callback2.WaitForResult();
4311  EXPECT_EQ(OK, rv);
4312
4313  EXPECT_TRUE(trans->IsReadyToRestartForAuth());
4314  TestCompletionCallback callback3;
4315  rv = trans->RestartWithAuth(AuthCredentials(), callback3.callback());
4316  EXPECT_EQ(ERR_IO_PENDING, rv);
4317  rv = callback3.WaitForResult();
4318  EXPECT_EQ(OK, rv);
4319  EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4320
4321  response = trans->GetResponseInfo();
4322  ASSERT_FALSE(response == NULL);
4323  EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
4324
4325  TestCompletionCallback callback4;
4326
4327  // Now enter the right password.
4328  rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kTestingNTLM),
4329                              callback4.callback());
4330  EXPECT_EQ(ERR_IO_PENDING, rv);
4331
4332  rv = callback4.WaitForResult();
4333  EXPECT_EQ(OK, rv);
4334
4335  EXPECT_TRUE(trans->IsReadyToRestartForAuth());
4336
4337  TestCompletionCallback callback5;
4338
4339  // One more roundtrip
4340  rv = trans->RestartWithAuth(AuthCredentials(), callback5.callback());
4341  EXPECT_EQ(ERR_IO_PENDING, rv);
4342
4343  rv = callback5.WaitForResult();
4344  EXPECT_EQ(OK, rv);
4345
4346  response = trans->GetResponseInfo();
4347  EXPECT_TRUE(response->auth_challenge.get() == NULL);
4348  EXPECT_EQ(13, response->headers->GetContentLength());
4349}
4350#endif  // NTLM_PORTABLE
4351
4352// Test reading a server response which has only headers, and no body.
4353// After some maximum number of bytes is consumed, the transaction should
4354// fail with ERR_RESPONSE_HEADERS_TOO_BIG.
4355TEST_P(HttpNetworkTransactionTest, LargeHeadersNoBody) {
4356  HttpRequestInfo request;
4357  request.method = "GET";
4358  request.url = GURL("http://www.google.com/");
4359  request.load_flags = 0;
4360
4361  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4362  scoped_ptr<HttpTransaction> trans(
4363      new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
4364
4365  // Respond with 300 kb of headers (we should fail after 256 kb).
4366  std::string large_headers_string;
4367  FillLargeHeadersString(&large_headers_string, 300 * 1024);
4368
4369  MockRead data_reads[] = {
4370    MockRead("HTTP/1.0 200 OK\r\n"),
4371    MockRead(ASYNC, large_headers_string.data(), large_headers_string.size()),
4372    MockRead("\r\nBODY"),
4373    MockRead(SYNCHRONOUS, OK),
4374  };
4375  StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
4376  session_deps_.socket_factory->AddSocketDataProvider(&data);
4377
4378  TestCompletionCallback callback;
4379
4380  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
4381  EXPECT_EQ(ERR_IO_PENDING, rv);
4382
4383  rv = callback.WaitForResult();
4384  EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG, rv);
4385
4386  const HttpResponseInfo* response = trans->GetResponseInfo();
4387  EXPECT_TRUE(response == NULL);
4388}
4389
4390// Make sure that we don't try to reuse a TCPClientSocket when failing to
4391// establish tunnel.
4392// http://code.google.com/p/chromium/issues/detail?id=3772
4393TEST_P(HttpNetworkTransactionTest,
4394       DontRecycleTransportSocketForSSLTunnel) {
4395  HttpRequestInfo request;
4396  request.method = "GET";
4397  request.url = GURL("https://www.google.com/");
4398  request.load_flags = 0;
4399
4400  // Configure against proxy server "myproxy:70".
4401  session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
4402
4403  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4404
4405  scoped_ptr<HttpTransaction> trans(
4406      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4407
4408  // Since we have proxy, should try to establish tunnel.
4409  MockWrite data_writes1[] = {
4410    MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4411              "Host: www.google.com\r\n"
4412              "Proxy-Connection: keep-alive\r\n\r\n"),
4413  };
4414
4415  // The proxy responds to the connect with a 404, using a persistent
4416  // connection. Usually a proxy would return 501 (not implemented),
4417  // or 200 (tunnel established).
4418  MockRead data_reads1[] = {
4419    MockRead("HTTP/1.1 404 Not Found\r\n"),
4420    MockRead("Content-Length: 10\r\n\r\n"),
4421    MockRead(SYNCHRONOUS, ERR_UNEXPECTED),  // Should not be reached.
4422  };
4423
4424  StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4425                                 data_writes1, arraysize(data_writes1));
4426  session_deps_.socket_factory->AddSocketDataProvider(&data1);
4427
4428  TestCompletionCallback callback1;
4429
4430  int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
4431  EXPECT_EQ(ERR_IO_PENDING, rv);
4432
4433  rv = callback1.WaitForResult();
4434  EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
4435
4436  const HttpResponseInfo* response = trans->GetResponseInfo();
4437  EXPECT_TRUE(response == NULL);
4438
4439  // Empty the current queue.  This is necessary because idle sockets are
4440  // added to the connection pool asynchronously with a PostTask.
4441  base::MessageLoop::current()->RunUntilIdle();
4442
4443  // We now check to make sure the TCPClientSocket was not added back to
4444  // the pool.
4445  EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
4446  trans.reset();
4447  base::MessageLoop::current()->RunUntilIdle();
4448  // Make sure that the socket didn't get recycled after calling the destructor.
4449  EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
4450}
4451
4452// Make sure that we recycle a socket after reading all of the response body.
4453TEST_P(HttpNetworkTransactionTest, RecycleSocket) {
4454  HttpRequestInfo request;
4455  request.method = "GET";
4456  request.url = GURL("http://www.google.com/");
4457  request.load_flags = 0;
4458
4459  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4460
4461  scoped_ptr<HttpTransaction> trans(
4462      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4463
4464  MockRead data_reads[] = {
4465    // A part of the response body is received with the response headers.
4466    MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
4467    // The rest of the response body is received in two parts.
4468    MockRead("lo"),
4469    MockRead(" world"),
4470    MockRead("junk"),  // Should not be read!!
4471    MockRead(SYNCHRONOUS, OK),
4472  };
4473
4474  StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
4475  session_deps_.socket_factory->AddSocketDataProvider(&data);
4476
4477  TestCompletionCallback callback;
4478
4479  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
4480  EXPECT_EQ(ERR_IO_PENDING, rv);
4481
4482  rv = callback.WaitForResult();
4483  EXPECT_EQ(OK, rv);
4484
4485  const HttpResponseInfo* response = trans->GetResponseInfo();
4486  ASSERT_TRUE(response != NULL);
4487
4488  EXPECT_TRUE(response->headers.get() != NULL);
4489  std::string status_line = response->headers->GetStatusLine();
4490  EXPECT_EQ("HTTP/1.1 200 OK", status_line);
4491
4492  EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
4493
4494  std::string response_data;
4495  rv = ReadTransaction(trans.get(), &response_data);
4496  EXPECT_EQ(OK, rv);
4497  EXPECT_EQ("hello world", response_data);
4498
4499  // Empty the current queue.  This is necessary because idle sockets are
4500  // added to the connection pool asynchronously with a PostTask.
4501  base::MessageLoop::current()->RunUntilIdle();
4502
4503  // We now check to make sure the socket was added back to the pool.
4504  EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
4505}
4506
4507// Make sure that we recycle a SSL socket after reading all of the response
4508// body.
4509TEST_P(HttpNetworkTransactionTest, RecycleSSLSocket) {
4510  HttpRequestInfo request;
4511  request.method = "GET";
4512  request.url = GURL("https://www.google.com/");
4513  request.load_flags = 0;
4514
4515  MockWrite data_writes[] = {
4516    MockWrite("GET / HTTP/1.1\r\n"
4517              "Host: www.google.com\r\n"
4518              "Connection: keep-alive\r\n\r\n"),
4519  };
4520
4521  MockRead data_reads[] = {
4522    MockRead("HTTP/1.1 200 OK\r\n"),
4523    MockRead("Content-Length: 11\r\n\r\n"),
4524    MockRead("hello world"),
4525    MockRead(SYNCHRONOUS, OK),
4526  };
4527
4528  SSLSocketDataProvider ssl(ASYNC, OK);
4529  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
4530
4531  StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4532                                data_writes, arraysize(data_writes));
4533  session_deps_.socket_factory->AddSocketDataProvider(&data);
4534
4535  TestCompletionCallback callback;
4536
4537  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4538  scoped_ptr<HttpTransaction> trans(
4539      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4540
4541  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
4542
4543  EXPECT_EQ(ERR_IO_PENDING, rv);
4544  EXPECT_EQ(OK, callback.WaitForResult());
4545
4546  const HttpResponseInfo* response = trans->GetResponseInfo();
4547  ASSERT_TRUE(response != NULL);
4548  ASSERT_TRUE(response->headers.get() != NULL);
4549  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4550
4551  EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
4552
4553  std::string response_data;
4554  rv = ReadTransaction(trans.get(), &response_data);
4555  EXPECT_EQ(OK, rv);
4556  EXPECT_EQ("hello world", response_data);
4557
4558  // Empty the current queue.  This is necessary because idle sockets are
4559  // added to the connection pool asynchronously with a PostTask.
4560  base::MessageLoop::current()->RunUntilIdle();
4561
4562  // We now check to make sure the socket was added back to the pool.
4563  EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
4564}
4565
4566// Grab a SSL socket, use it, and put it back into the pool.  Then, reuse it
4567// from the pool and make sure that we recover okay.
4568TEST_P(HttpNetworkTransactionTest, RecycleDeadSSLSocket) {
4569  HttpRequestInfo request;
4570  request.method = "GET";
4571  request.url = GURL("https://www.google.com/");
4572  request.load_flags = 0;
4573
4574  MockWrite data_writes[] = {
4575    MockWrite("GET / HTTP/1.1\r\n"
4576              "Host: www.google.com\r\n"
4577              "Connection: keep-alive\r\n\r\n"),
4578    MockWrite("GET / HTTP/1.1\r\n"
4579              "Host: www.google.com\r\n"
4580              "Connection: keep-alive\r\n\r\n"),
4581  };
4582
4583  MockRead data_reads[] = {
4584    MockRead("HTTP/1.1 200 OK\r\n"),
4585    MockRead("Content-Length: 11\r\n\r\n"),
4586    MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
4587    MockRead("hello world"),
4588    MockRead(ASYNC, 0, 0)   // EOF
4589  };
4590
4591  SSLSocketDataProvider ssl(ASYNC, OK);
4592  SSLSocketDataProvider ssl2(ASYNC, OK);
4593  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
4594  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
4595
4596  StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4597                                data_writes, arraysize(data_writes));
4598  StaticSocketDataProvider data2(data_reads, arraysize(data_reads),
4599                                data_writes, arraysize(data_writes));
4600  session_deps_.socket_factory->AddSocketDataProvider(&data);
4601  session_deps_.socket_factory->AddSocketDataProvider(&data2);
4602
4603  TestCompletionCallback callback;
4604
4605  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4606  scoped_ptr<HttpTransaction> trans(
4607      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4608
4609  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
4610
4611  EXPECT_EQ(ERR_IO_PENDING, rv);
4612  EXPECT_EQ(OK, callback.WaitForResult());
4613
4614  const HttpResponseInfo* response = trans->GetResponseInfo();
4615  ASSERT_TRUE(response != NULL);
4616  ASSERT_TRUE(response->headers.get() != NULL);
4617  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4618
4619  EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
4620
4621  std::string response_data;
4622  rv = ReadTransaction(trans.get(), &response_data);
4623  EXPECT_EQ(OK, rv);
4624  EXPECT_EQ("hello world", response_data);
4625
4626  // Empty the current queue.  This is necessary because idle sockets are
4627  // added to the connection pool asynchronously with a PostTask.
4628  base::MessageLoop::current()->RunUntilIdle();
4629
4630  // We now check to make sure the socket was added back to the pool.
4631  EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
4632
4633  // Now start the second transaction, which should reuse the previous socket.
4634
4635  trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4636
4637  rv = trans->Start(&request, callback.callback(), BoundNetLog());
4638
4639  EXPECT_EQ(ERR_IO_PENDING, rv);
4640  EXPECT_EQ(OK, callback.WaitForResult());
4641
4642  response = trans->GetResponseInfo();
4643  ASSERT_TRUE(response != NULL);
4644  ASSERT_TRUE(response->headers.get() != NULL);
4645  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4646
4647  EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
4648
4649  rv = ReadTransaction(trans.get(), &response_data);
4650  EXPECT_EQ(OK, rv);
4651  EXPECT_EQ("hello world", response_data);
4652
4653  // Empty the current queue.  This is necessary because idle sockets are
4654  // added to the connection pool asynchronously with a PostTask.
4655  base::MessageLoop::current()->RunUntilIdle();
4656
4657  // We now check to make sure the socket was added back to the pool.
4658  EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
4659}
4660
4661// Make sure that we recycle a socket after a zero-length response.
4662// http://crbug.com/9880
4663TEST_P(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
4664  HttpRequestInfo request;
4665  request.method = "GET";
4666  request.url = GURL("http://www.google.com/csi?v=3&s=web&action=&"
4667                     "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
4668                     "e=17259,18167,19592,19773,19981,20133,20173,20233&"
4669                     "rt=prt.2642,ol.2649,xjs.2951");
4670  request.load_flags = 0;
4671
4672  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4673
4674  scoped_ptr<HttpTransaction> trans(
4675      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4676
4677  MockRead data_reads[] = {
4678    MockRead("HTTP/1.1 204 No Content\r\n"
4679             "Content-Length: 0\r\n"
4680             "Content-Type: text/html\r\n\r\n"),
4681    MockRead("junk"),  // Should not be read!!
4682    MockRead(SYNCHRONOUS, OK),
4683  };
4684
4685  StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
4686  session_deps_.socket_factory->AddSocketDataProvider(&data);
4687
4688  TestCompletionCallback callback;
4689
4690  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
4691  EXPECT_EQ(ERR_IO_PENDING, rv);
4692
4693  rv = callback.WaitForResult();
4694  EXPECT_EQ(OK, rv);
4695
4696  const HttpResponseInfo* response = trans->GetResponseInfo();
4697  ASSERT_TRUE(response != NULL);
4698
4699  EXPECT_TRUE(response->headers.get() != NULL);
4700  std::string status_line = response->headers->GetStatusLine();
4701  EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
4702
4703  EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
4704
4705  std::string response_data;
4706  rv = ReadTransaction(trans.get(), &response_data);
4707  EXPECT_EQ(OK, rv);
4708  EXPECT_EQ("", response_data);
4709
4710  // Empty the current queue.  This is necessary because idle sockets are
4711  // added to the connection pool asynchronously with a PostTask.
4712  base::MessageLoop::current()->RunUntilIdle();
4713
4714  // We now check to make sure the socket was added back to the pool.
4715  EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
4716}
4717
4718TEST_P(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
4719  ScopedVector<UploadElementReader> element_readers;
4720  element_readers.push_back(new UploadBytesElementReader("foo", 3));
4721  UploadDataStream upload_data_stream(element_readers.Pass(), 0);
4722
4723  HttpRequestInfo request[2];
4724  // Transaction 1: a GET request that succeeds.  The socket is recycled
4725  // after use.
4726  request[0].method = "GET";
4727  request[0].url = GURL("http://www.google.com/");
4728  request[0].load_flags = 0;
4729  // Transaction 2: a POST request.  Reuses the socket kept alive from
4730  // transaction 1.  The first attempts fails when writing the POST data.
4731  // This causes the transaction to retry with a new socket.  The second
4732  // attempt succeeds.
4733  request[1].method = "POST";
4734  request[1].url = GURL("http://www.google.com/login.cgi");
4735  request[1].upload_data_stream = &upload_data_stream;
4736  request[1].load_flags = 0;
4737
4738  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4739
4740  // The first socket is used for transaction 1 and the first attempt of
4741  // transaction 2.
4742
4743  // The response of transaction 1.
4744  MockRead data_reads1[] = {
4745    MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
4746    MockRead("hello world"),
4747    MockRead(SYNCHRONOUS, OK),
4748  };
4749  // The mock write results of transaction 1 and the first attempt of
4750  // transaction 2.
4751  MockWrite data_writes1[] = {
4752    MockWrite(SYNCHRONOUS, 64),  // GET
4753    MockWrite(SYNCHRONOUS, 93),  // POST
4754    MockWrite(SYNCHRONOUS, ERR_CONNECTION_ABORTED),  // POST data
4755  };
4756  StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4757                                 data_writes1, arraysize(data_writes1));
4758
4759  // The second socket is used for the second attempt of transaction 2.
4760
4761  // The response of transaction 2.
4762  MockRead data_reads2[] = {
4763    MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
4764    MockRead("welcome"),
4765    MockRead(SYNCHRONOUS, OK),
4766  };
4767  // The mock write results of the second attempt of transaction 2.
4768  MockWrite data_writes2[] = {
4769    MockWrite(SYNCHRONOUS, 93),  // POST
4770    MockWrite(SYNCHRONOUS, 3),  // POST data
4771  };
4772  StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4773                                 data_writes2, arraysize(data_writes2));
4774
4775  session_deps_.socket_factory->AddSocketDataProvider(&data1);
4776  session_deps_.socket_factory->AddSocketDataProvider(&data2);
4777
4778  const char* kExpectedResponseData[] = {
4779    "hello world", "welcome"
4780  };
4781
4782  for (int i = 0; i < 2; ++i) {
4783    scoped_ptr<HttpTransaction> trans(
4784        new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4785
4786    TestCompletionCallback callback;
4787
4788    int rv = trans->Start(&request[i], callback.callback(), BoundNetLog());
4789    EXPECT_EQ(ERR_IO_PENDING, rv);
4790
4791    rv = callback.WaitForResult();
4792    EXPECT_EQ(OK, rv);
4793
4794    const HttpResponseInfo* response = trans->GetResponseInfo();
4795    ASSERT_TRUE(response != NULL);
4796
4797    EXPECT_TRUE(response->headers.get() != NULL);
4798    EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4799
4800    std::string response_data;
4801    rv = ReadTransaction(trans.get(), &response_data);
4802    EXPECT_EQ(OK, rv);
4803    EXPECT_EQ(kExpectedResponseData[i], response_data);
4804  }
4805}
4806
4807// Test the request-challenge-retry sequence for basic auth when there is
4808// an identity in the URL. The request should be sent as normal, but when
4809// it fails the identity from the URL is used to answer the challenge.
4810TEST_P(HttpNetworkTransactionTest, AuthIdentityInURL) {
4811  HttpRequestInfo request;
4812  request.method = "GET";
4813  request.url = GURL("http://foo:b@r@www.google.com/");
4814  request.load_flags = LOAD_NORMAL;
4815
4816  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4817  scoped_ptr<HttpTransaction> trans(
4818      new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
4819
4820  // The password contains an escaped character -- for this test to pass it
4821  // will need to be unescaped by HttpNetworkTransaction.
4822  EXPECT_EQ("b%40r", request.url.password());
4823
4824  MockWrite data_writes1[] = {
4825    MockWrite("GET / HTTP/1.1\r\n"
4826              "Host: www.google.com\r\n"
4827              "Connection: keep-alive\r\n\r\n"),
4828  };
4829
4830  MockRead data_reads1[] = {
4831    MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4832    MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4833    MockRead("Content-Length: 10\r\n\r\n"),
4834    MockRead(SYNCHRONOUS, ERR_FAILED),
4835  };
4836
4837  // After the challenge above, the transaction will be restarted using the
4838  // identity from the url (foo, b@r) to answer the challenge.
4839  MockWrite data_writes2[] = {
4840    MockWrite("GET / HTTP/1.1\r\n"
4841              "Host: www.google.com\r\n"
4842              "Connection: keep-alive\r\n"
4843              "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
4844  };
4845
4846  MockRead data_reads2[] = {
4847    MockRead("HTTP/1.0 200 OK\r\n"),
4848    MockRead("Content-Length: 100\r\n\r\n"),
4849    MockRead(SYNCHRONOUS, OK),
4850  };
4851
4852  StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4853                                 data_writes1, arraysize(data_writes1));
4854  StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4855                                 data_writes2, arraysize(data_writes2));
4856  session_deps_.socket_factory->AddSocketDataProvider(&data1);
4857  session_deps_.socket_factory->AddSocketDataProvider(&data2);
4858
4859  TestCompletionCallback callback1;
4860  int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
4861  EXPECT_EQ(ERR_IO_PENDING, rv);
4862  rv = callback1.WaitForResult();
4863  EXPECT_EQ(OK, rv);
4864  EXPECT_TRUE(trans->IsReadyToRestartForAuth());
4865
4866  TestCompletionCallback callback2;
4867  rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
4868  EXPECT_EQ(ERR_IO_PENDING, rv);
4869  rv = callback2.WaitForResult();
4870  EXPECT_EQ(OK, rv);
4871  EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4872
4873  const HttpResponseInfo* response = trans->GetResponseInfo();
4874  ASSERT_TRUE(response != NULL);
4875
4876  // There is no challenge info, since the identity in URL worked.
4877  EXPECT_TRUE(response->auth_challenge.get() == NULL);
4878
4879  EXPECT_EQ(100, response->headers->GetContentLength());
4880
4881  // Empty the current queue.
4882  base::MessageLoop::current()->RunUntilIdle();
4883}
4884
4885// Test the request-challenge-retry sequence for basic auth when there is an
4886// incorrect identity in the URL. The identity from the URL should be used only
4887// once.
4888TEST_P(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
4889  HttpRequestInfo request;
4890  request.method = "GET";
4891  // Note: the URL has a username:password in it.  The password "baz" is
4892  // wrong (should be "bar").
4893  request.url = GURL("http://foo:baz@www.google.com/");
4894
4895  request.load_flags = LOAD_NORMAL;
4896
4897  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4898  scoped_ptr<HttpTransaction> trans(
4899      new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
4900
4901  MockWrite data_writes1[] = {
4902    MockWrite("GET / HTTP/1.1\r\n"
4903              "Host: www.google.com\r\n"
4904              "Connection: keep-alive\r\n\r\n"),
4905  };
4906
4907  MockRead data_reads1[] = {
4908    MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4909    MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4910    MockRead("Content-Length: 10\r\n\r\n"),
4911    MockRead(SYNCHRONOUS, ERR_FAILED),
4912  };
4913
4914  // After the challenge above, the transaction will be restarted using the
4915  // identity from the url (foo, baz) to answer the challenge.
4916  MockWrite data_writes2[] = {
4917    MockWrite("GET / HTTP/1.1\r\n"
4918              "Host: www.google.com\r\n"
4919              "Connection: keep-alive\r\n"
4920              "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
4921  };
4922
4923  MockRead data_reads2[] = {
4924    MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4925    MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4926    MockRead("Content-Length: 10\r\n\r\n"),
4927    MockRead(SYNCHRONOUS, ERR_FAILED),
4928  };
4929
4930  // After the challenge above, the transaction will be restarted using the
4931  // identity supplied by the user (foo, bar) to answer the challenge.
4932  MockWrite data_writes3[] = {
4933    MockWrite("GET / HTTP/1.1\r\n"
4934              "Host: www.google.com\r\n"
4935              "Connection: keep-alive\r\n"
4936              "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4937  };
4938
4939  MockRead data_reads3[] = {
4940    MockRead("HTTP/1.0 200 OK\r\n"),
4941    MockRead("Content-Length: 100\r\n\r\n"),
4942    MockRead(SYNCHRONOUS, OK),
4943  };
4944
4945  StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4946                                 data_writes1, arraysize(data_writes1));
4947  StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4948                                 data_writes2, arraysize(data_writes2));
4949  StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
4950                                 data_writes3, arraysize(data_writes3));
4951  session_deps_.socket_factory->AddSocketDataProvider(&data1);
4952  session_deps_.socket_factory->AddSocketDataProvider(&data2);
4953  session_deps_.socket_factory->AddSocketDataProvider(&data3);
4954
4955  TestCompletionCallback callback1;
4956
4957  int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
4958  EXPECT_EQ(ERR_IO_PENDING, rv);
4959
4960  rv = callback1.WaitForResult();
4961  EXPECT_EQ(OK, rv);
4962
4963  EXPECT_TRUE(trans->IsReadyToRestartForAuth());
4964  TestCompletionCallback callback2;
4965  rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
4966  EXPECT_EQ(ERR_IO_PENDING, rv);
4967  rv = callback2.WaitForResult();
4968  EXPECT_EQ(OK, rv);
4969  EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4970
4971  const HttpResponseInfo* response = trans->GetResponseInfo();
4972  ASSERT_TRUE(response != NULL);
4973  EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
4974
4975  TestCompletionCallback callback3;
4976  rv = trans->RestartWithAuth(
4977      AuthCredentials(kFoo, kBar), callback3.callback());
4978  EXPECT_EQ(ERR_IO_PENDING, rv);
4979  rv = callback3.WaitForResult();
4980  EXPECT_EQ(OK, rv);
4981  EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4982
4983  response = trans->GetResponseInfo();
4984  ASSERT_TRUE(response != NULL);
4985
4986  // There is no challenge info, since the identity worked.
4987  EXPECT_TRUE(response->auth_challenge.get() == NULL);
4988
4989  EXPECT_EQ(100, response->headers->GetContentLength());
4990
4991  // Empty the current queue.
4992  base::MessageLoop::current()->RunUntilIdle();
4993}
4994
4995
4996// Test the request-challenge-retry sequence for basic auth when there is a
4997// correct identity in the URL, but its use is being suppressed. The identity
4998// from the URL should never be used.
4999TEST_P(HttpNetworkTransactionTest, AuthIdentityInURLSuppressed) {
5000  HttpRequestInfo request;
5001  request.method = "GET";
5002  request.url = GURL("http://foo:bar@www.google.com/");
5003  request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
5004
5005  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5006  scoped_ptr<HttpTransaction> trans(
5007      new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
5008
5009  MockWrite data_writes1[] = {
5010    MockWrite("GET / HTTP/1.1\r\n"
5011              "Host: www.google.com\r\n"
5012              "Connection: keep-alive\r\n\r\n"),
5013  };
5014
5015  MockRead data_reads1[] = {
5016    MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5017    MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5018    MockRead("Content-Length: 10\r\n\r\n"),
5019    MockRead(SYNCHRONOUS, ERR_FAILED),
5020  };
5021
5022  // After the challenge above, the transaction will be restarted using the
5023  // identity supplied by the user, not the one in the URL, to answer the
5024  // challenge.
5025  MockWrite data_writes3[] = {
5026    MockWrite("GET / HTTP/1.1\r\n"
5027              "Host: www.google.com\r\n"
5028              "Connection: keep-alive\r\n"
5029              "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5030  };
5031
5032  MockRead data_reads3[] = {
5033    MockRead("HTTP/1.0 200 OK\r\n"),
5034    MockRead("Content-Length: 100\r\n\r\n"),
5035    MockRead(SYNCHRONOUS, OK),
5036  };
5037
5038  StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5039                                 data_writes1, arraysize(data_writes1));
5040  StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
5041                                 data_writes3, arraysize(data_writes3));
5042  session_deps_.socket_factory->AddSocketDataProvider(&data1);
5043  session_deps_.socket_factory->AddSocketDataProvider(&data3);
5044
5045  TestCompletionCallback callback1;
5046  int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5047  EXPECT_EQ(ERR_IO_PENDING, rv);
5048  rv = callback1.WaitForResult();
5049  EXPECT_EQ(OK, rv);
5050  EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5051
5052  const HttpResponseInfo* response = trans->GetResponseInfo();
5053  ASSERT_TRUE(response != NULL);
5054  EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
5055
5056  TestCompletionCallback callback3;
5057  rv = trans->RestartWithAuth(
5058      AuthCredentials(kFoo, kBar), callback3.callback());
5059  EXPECT_EQ(ERR_IO_PENDING, rv);
5060  rv = callback3.WaitForResult();
5061  EXPECT_EQ(OK, rv);
5062  EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5063
5064  response = trans->GetResponseInfo();
5065  ASSERT_TRUE(response != NULL);
5066
5067  // There is no challenge info, since the identity worked.
5068  EXPECT_TRUE(response->auth_challenge.get() == NULL);
5069  EXPECT_EQ(100, response->headers->GetContentLength());
5070
5071  // Empty the current queue.
5072  base::MessageLoop::current()->RunUntilIdle();
5073}
5074
5075// Test that previously tried username/passwords for a realm get re-used.
5076TEST_P(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
5077  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5078
5079  // Transaction 1: authenticate (foo, bar) on MyRealm1
5080  {
5081    HttpRequestInfo request;
5082    request.method = "GET";
5083    request.url = GURL("http://www.google.com/x/y/z");
5084    request.load_flags = 0;
5085
5086    scoped_ptr<HttpTransaction> trans(
5087        new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5088
5089    MockWrite data_writes1[] = {
5090      MockWrite("GET /x/y/z HTTP/1.1\r\n"
5091                "Host: www.google.com\r\n"
5092                "Connection: keep-alive\r\n\r\n"),
5093    };
5094
5095    MockRead data_reads1[] = {
5096      MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5097      MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5098      MockRead("Content-Length: 10000\r\n\r\n"),
5099      MockRead(SYNCHRONOUS, ERR_FAILED),
5100    };
5101
5102    // Resend with authorization (username=foo, password=bar)
5103    MockWrite data_writes2[] = {
5104      MockWrite("GET /x/y/z HTTP/1.1\r\n"
5105                "Host: www.google.com\r\n"
5106                "Connection: keep-alive\r\n"
5107                "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5108    };
5109
5110    // Sever accepts the authorization.
5111    MockRead data_reads2[] = {
5112      MockRead("HTTP/1.0 200 OK\r\n"),
5113      MockRead("Content-Length: 100\r\n\r\n"),
5114      MockRead(SYNCHRONOUS, OK),
5115    };
5116
5117    StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5118                                   data_writes1, arraysize(data_writes1));
5119    StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5120                                   data_writes2, arraysize(data_writes2));
5121    session_deps_.socket_factory->AddSocketDataProvider(&data1);
5122    session_deps_.socket_factory->AddSocketDataProvider(&data2);
5123
5124    TestCompletionCallback callback1;
5125
5126    int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5127    EXPECT_EQ(ERR_IO_PENDING, rv);
5128
5129    rv = callback1.WaitForResult();
5130    EXPECT_EQ(OK, rv);
5131
5132    const HttpResponseInfo* response = trans->GetResponseInfo();
5133    ASSERT_TRUE(response != NULL);
5134    EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
5135
5136    TestCompletionCallback callback2;
5137
5138    rv = trans->RestartWithAuth(
5139        AuthCredentials(kFoo, kBar), callback2.callback());
5140    EXPECT_EQ(ERR_IO_PENDING, rv);
5141
5142    rv = callback2.WaitForResult();
5143    EXPECT_EQ(OK, rv);
5144
5145    response = trans->GetResponseInfo();
5146    ASSERT_TRUE(response != NULL);
5147    EXPECT_TRUE(response->auth_challenge.get() == NULL);
5148    EXPECT_EQ(100, response->headers->GetContentLength());
5149  }
5150
5151  // ------------------------------------------------------------------------
5152
5153  // Transaction 2: authenticate (foo2, bar2) on MyRealm2
5154  {
5155    HttpRequestInfo request;
5156    request.method = "GET";
5157    // Note that Transaction 1 was at /x/y/z, so this is in the same
5158    // protection space as MyRealm1.
5159    request.url = GURL("http://www.google.com/x/y/a/b");
5160    request.load_flags = 0;
5161
5162    scoped_ptr<HttpTransaction> trans(
5163        new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5164
5165    MockWrite data_writes1[] = {
5166      MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
5167                "Host: www.google.com\r\n"
5168                "Connection: keep-alive\r\n"
5169                // Send preemptive authorization for MyRealm1
5170                "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5171    };
5172
5173    // The server didn't like the preemptive authorization, and
5174    // challenges us for a different realm (MyRealm2).
5175    MockRead data_reads1[] = {
5176      MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5177      MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
5178      MockRead("Content-Length: 10000\r\n\r\n"),
5179      MockRead(SYNCHRONOUS, ERR_FAILED),
5180    };
5181
5182    // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
5183    MockWrite data_writes2[] = {
5184      MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
5185                "Host: www.google.com\r\n"
5186                "Connection: keep-alive\r\n"
5187                "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
5188    };
5189
5190    // Sever accepts the authorization.
5191    MockRead data_reads2[] = {
5192      MockRead("HTTP/1.0 200 OK\r\n"),
5193      MockRead("Content-Length: 100\r\n\r\n"),
5194      MockRead(SYNCHRONOUS, OK),
5195    };
5196
5197    StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5198                                   data_writes1, arraysize(data_writes1));
5199    StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5200                                   data_writes2, arraysize(data_writes2));
5201    session_deps_.socket_factory->AddSocketDataProvider(&data1);
5202    session_deps_.socket_factory->AddSocketDataProvider(&data2);
5203
5204    TestCompletionCallback callback1;
5205
5206    int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5207    EXPECT_EQ(ERR_IO_PENDING, rv);
5208
5209    rv = callback1.WaitForResult();
5210    EXPECT_EQ(OK, rv);
5211
5212    const HttpResponseInfo* response = trans->GetResponseInfo();
5213    ASSERT_TRUE(response != NULL);
5214    ASSERT_TRUE(response->auth_challenge.get());
5215    EXPECT_FALSE(response->auth_challenge->is_proxy);
5216    EXPECT_EQ("www.google.com:80",
5217              response->auth_challenge->challenger.ToString());
5218    EXPECT_EQ("MyRealm2", response->auth_challenge->realm);
5219    EXPECT_EQ("basic", response->auth_challenge->scheme);
5220
5221    TestCompletionCallback callback2;
5222
5223    rv = trans->RestartWithAuth(
5224        AuthCredentials(kFoo2, kBar2), callback2.callback());
5225    EXPECT_EQ(ERR_IO_PENDING, rv);
5226
5227    rv = callback2.WaitForResult();
5228    EXPECT_EQ(OK, rv);
5229
5230    response = trans->GetResponseInfo();
5231    ASSERT_TRUE(response != NULL);
5232    EXPECT_TRUE(response->auth_challenge.get() == NULL);
5233    EXPECT_EQ(100, response->headers->GetContentLength());
5234  }
5235
5236  // ------------------------------------------------------------------------
5237
5238  // Transaction 3: Resend a request in MyRealm's protection space --
5239  // succeed with preemptive authorization.
5240  {
5241    HttpRequestInfo request;
5242    request.method = "GET";
5243    request.url = GURL("http://www.google.com/x/y/z2");
5244    request.load_flags = 0;
5245
5246    scoped_ptr<HttpTransaction> trans(
5247        new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5248
5249    MockWrite data_writes1[] = {
5250      MockWrite("GET /x/y/z2 HTTP/1.1\r\n"
5251                "Host: www.google.com\r\n"
5252                "Connection: keep-alive\r\n"
5253                // The authorization for MyRealm1 gets sent preemptively
5254                // (since the url is in the same protection space)
5255                "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5256    };
5257
5258    // Sever accepts the preemptive authorization
5259    MockRead data_reads1[] = {
5260      MockRead("HTTP/1.0 200 OK\r\n"),
5261      MockRead("Content-Length: 100\r\n\r\n"),
5262      MockRead(SYNCHRONOUS, OK),
5263    };
5264
5265    StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5266                                   data_writes1, arraysize(data_writes1));
5267    session_deps_.socket_factory->AddSocketDataProvider(&data1);
5268
5269    TestCompletionCallback callback1;
5270
5271    int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5272    EXPECT_EQ(ERR_IO_PENDING, rv);
5273
5274    rv = callback1.WaitForResult();
5275    EXPECT_EQ(OK, rv);
5276
5277    const HttpResponseInfo* response = trans->GetResponseInfo();
5278    ASSERT_TRUE(response != NULL);
5279
5280    EXPECT_TRUE(response->auth_challenge.get() == NULL);
5281    EXPECT_EQ(100, response->headers->GetContentLength());
5282  }
5283
5284  // ------------------------------------------------------------------------
5285
5286  // Transaction 4: request another URL in MyRealm (however the
5287  // url is not known to belong to the protection space, so no pre-auth).
5288  {
5289    HttpRequestInfo request;
5290    request.method = "GET";
5291    request.url = GURL("http://www.google.com/x/1");
5292    request.load_flags = 0;
5293
5294    scoped_ptr<HttpTransaction> trans(
5295        new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5296
5297    MockWrite data_writes1[] = {
5298      MockWrite("GET /x/1 HTTP/1.1\r\n"
5299                "Host: www.google.com\r\n"
5300                "Connection: keep-alive\r\n\r\n"),
5301    };
5302
5303    MockRead data_reads1[] = {
5304      MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5305      MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5306      MockRead("Content-Length: 10000\r\n\r\n"),
5307      MockRead(SYNCHRONOUS, ERR_FAILED),
5308    };
5309
5310    // Resend with authorization from MyRealm's cache.
5311    MockWrite data_writes2[] = {
5312      MockWrite("GET /x/1 HTTP/1.1\r\n"
5313                "Host: www.google.com\r\n"
5314                "Connection: keep-alive\r\n"
5315                "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5316    };
5317
5318    // Sever accepts the authorization.
5319    MockRead data_reads2[] = {
5320      MockRead("HTTP/1.0 200 OK\r\n"),
5321      MockRead("Content-Length: 100\r\n\r\n"),
5322      MockRead(SYNCHRONOUS, OK),
5323    };
5324
5325    StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5326                                   data_writes1, arraysize(data_writes1));
5327    StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5328                                   data_writes2, arraysize(data_writes2));
5329    session_deps_.socket_factory->AddSocketDataProvider(&data1);
5330    session_deps_.socket_factory->AddSocketDataProvider(&data2);
5331
5332    TestCompletionCallback callback1;
5333
5334    int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5335    EXPECT_EQ(ERR_IO_PENDING, rv);
5336
5337    rv = callback1.WaitForResult();
5338    EXPECT_EQ(OK, rv);
5339
5340    EXPECT_TRUE(trans->IsReadyToRestartForAuth());
5341    TestCompletionCallback callback2;
5342    rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
5343    EXPECT_EQ(ERR_IO_PENDING, rv);
5344    rv = callback2.WaitForResult();
5345    EXPECT_EQ(OK, rv);
5346    EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5347
5348    const HttpResponseInfo* response = trans->GetResponseInfo();
5349    ASSERT_TRUE(response != NULL);
5350    EXPECT_TRUE(response->auth_challenge.get() == NULL);
5351    EXPECT_EQ(100, response->headers->GetContentLength());
5352  }
5353
5354  // ------------------------------------------------------------------------
5355
5356  // Transaction 5: request a URL in MyRealm, but the server rejects the
5357  // cached identity. Should invalidate and re-prompt.
5358  {
5359    HttpRequestInfo request;
5360    request.method = "GET";
5361    request.url = GURL("http://www.google.com/p/q/t");
5362    request.load_flags = 0;
5363
5364    scoped_ptr<HttpTransaction> trans(
5365        new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5366
5367    MockWrite data_writes1[] = {
5368      MockWrite("GET /p/q/t HTTP/1.1\r\n"
5369                "Host: www.google.com\r\n"
5370                "Connection: keep-alive\r\n\r\n"),
5371    };
5372
5373    MockRead data_reads1[] = {
5374      MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5375      MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5376      MockRead("Content-Length: 10000\r\n\r\n"),
5377      MockRead(SYNCHRONOUS, ERR_FAILED),
5378    };
5379
5380    // Resend with authorization from cache for MyRealm.
5381    MockWrite data_writes2[] = {
5382      MockWrite("GET /p/q/t HTTP/1.1\r\n"
5383                "Host: www.google.com\r\n"
5384                "Connection: keep-alive\r\n"
5385                "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5386    };
5387
5388    // Sever rejects the authorization.
5389    MockRead data_reads2[] = {
5390      MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5391      MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5392      MockRead("Content-Length: 10000\r\n\r\n"),
5393      MockRead(SYNCHRONOUS, ERR_FAILED),
5394    };
5395
5396    // At this point we should prompt for new credentials for MyRealm.
5397    // Restart with username=foo3, password=foo4.
5398    MockWrite data_writes3[] = {
5399      MockWrite("GET /p/q/t HTTP/1.1\r\n"
5400                "Host: www.google.com\r\n"
5401                "Connection: keep-alive\r\n"
5402                "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
5403    };
5404
5405    // Sever accepts the authorization.
5406    MockRead data_reads3[] = {
5407      MockRead("HTTP/1.0 200 OK\r\n"),
5408      MockRead("Content-Length: 100\r\n\r\n"),
5409      MockRead(SYNCHRONOUS, OK),
5410    };
5411
5412    StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5413                                   data_writes1, arraysize(data_writes1));
5414    StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5415                                   data_writes2, arraysize(data_writes2));
5416    StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
5417                                   data_writes3, arraysize(data_writes3));
5418    session_deps_.socket_factory->AddSocketDataProvider(&data1);
5419    session_deps_.socket_factory->AddSocketDataProvider(&data2);
5420    session_deps_.socket_factory->AddSocketDataProvider(&data3);
5421
5422    TestCompletionCallback callback1;
5423
5424    int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5425    EXPECT_EQ(ERR_IO_PENDING, rv);
5426
5427    rv = callback1.WaitForResult();
5428    EXPECT_EQ(OK, rv);
5429
5430    EXPECT_TRUE(trans->IsReadyToRestartForAuth());
5431    TestCompletionCallback callback2;
5432    rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
5433    EXPECT_EQ(ERR_IO_PENDING, rv);
5434    rv = callback2.WaitForResult();
5435    EXPECT_EQ(OK, rv);
5436    EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5437
5438    const HttpResponseInfo* response = trans->GetResponseInfo();
5439    ASSERT_TRUE(response != NULL);
5440    EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
5441
5442    TestCompletionCallback callback3;
5443
5444    rv = trans->RestartWithAuth(
5445        AuthCredentials(kFoo3, kBar3), callback3.callback());
5446    EXPECT_EQ(ERR_IO_PENDING, rv);
5447
5448    rv = callback3.WaitForResult();
5449    EXPECT_EQ(OK, rv);
5450
5451    response = trans->GetResponseInfo();
5452    ASSERT_TRUE(response != NULL);
5453    EXPECT_TRUE(response->auth_challenge.get() == NULL);
5454    EXPECT_EQ(100, response->headers->GetContentLength());
5455  }
5456}
5457
5458// Tests that nonce count increments when multiple auth attempts
5459// are started with the same nonce.
5460TEST_P(HttpNetworkTransactionTest, DigestPreAuthNonceCount) {
5461  HttpAuthHandlerDigest::Factory* digest_factory =
5462      new HttpAuthHandlerDigest::Factory();
5463  HttpAuthHandlerDigest::FixedNonceGenerator* nonce_generator =
5464      new HttpAuthHandlerDigest::FixedNonceGenerator("0123456789abcdef");
5465  digest_factory->set_nonce_generator(nonce_generator);
5466  session_deps_.http_auth_handler_factory.reset(digest_factory);
5467  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5468
5469  // Transaction 1: authenticate (foo, bar) on MyRealm1
5470  {
5471    HttpRequestInfo request;
5472    request.method = "GET";
5473    request.url = GURL("http://www.google.com/x/y/z");
5474    request.load_flags = 0;
5475
5476    scoped_ptr<HttpTransaction> trans(
5477        new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5478
5479    MockWrite data_writes1[] = {
5480      MockWrite("GET /x/y/z HTTP/1.1\r\n"
5481                "Host: www.google.com\r\n"
5482                "Connection: keep-alive\r\n\r\n"),
5483    };
5484
5485    MockRead data_reads1[] = {
5486      MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5487      MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
5488               "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
5489      MockRead(SYNCHRONOUS, OK),
5490    };
5491
5492    // Resend with authorization (username=foo, password=bar)
5493    MockWrite data_writes2[] = {
5494      MockWrite("GET /x/y/z HTTP/1.1\r\n"
5495                "Host: www.google.com\r\n"
5496                "Connection: keep-alive\r\n"
5497                "Authorization: Digest username=\"foo\", realm=\"digestive\", "
5498                "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
5499                "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
5500                "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
5501    };
5502
5503    // Sever accepts the authorization.
5504    MockRead data_reads2[] = {
5505      MockRead("HTTP/1.0 200 OK\r\n"),
5506      MockRead(SYNCHRONOUS, OK),
5507    };
5508
5509    StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5510                                   data_writes1, arraysize(data_writes1));
5511    StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5512                                   data_writes2, arraysize(data_writes2));
5513    session_deps_.socket_factory->AddSocketDataProvider(&data1);
5514    session_deps_.socket_factory->AddSocketDataProvider(&data2);
5515
5516    TestCompletionCallback callback1;
5517
5518    int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5519    EXPECT_EQ(ERR_IO_PENDING, rv);
5520
5521    rv = callback1.WaitForResult();
5522    EXPECT_EQ(OK, rv);
5523
5524    const HttpResponseInfo* response = trans->GetResponseInfo();
5525    ASSERT_TRUE(response != NULL);
5526    EXPECT_TRUE(CheckDigestServerAuth(response->auth_challenge.get()));
5527
5528    TestCompletionCallback callback2;
5529
5530    rv = trans->RestartWithAuth(
5531        AuthCredentials(kFoo, kBar), callback2.callback());
5532    EXPECT_EQ(ERR_IO_PENDING, rv);
5533
5534    rv = callback2.WaitForResult();
5535    EXPECT_EQ(OK, rv);
5536
5537    response = trans->GetResponseInfo();
5538    ASSERT_TRUE(response != NULL);
5539    EXPECT_TRUE(response->auth_challenge.get() == NULL);
5540  }
5541
5542  // ------------------------------------------------------------------------
5543
5544  // Transaction 2: Request another resource in digestive's protection space.
5545  // This will preemptively add an Authorization header which should have an
5546  // "nc" value of 2 (as compared to 1 in the first use.
5547  {
5548    HttpRequestInfo request;
5549    request.method = "GET";
5550    // Note that Transaction 1 was at /x/y/z, so this is in the same
5551    // protection space as digest.
5552    request.url = GURL("http://www.google.com/x/y/a/b");
5553    request.load_flags = 0;
5554
5555    scoped_ptr<HttpTransaction> trans(
5556        new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5557
5558    MockWrite data_writes1[] = {
5559      MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
5560                "Host: www.google.com\r\n"
5561                "Connection: keep-alive\r\n"
5562                "Authorization: Digest username=\"foo\", realm=\"digestive\", "
5563                "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
5564                "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
5565                "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
5566    };
5567
5568    // Sever accepts the authorization.
5569    MockRead data_reads1[] = {
5570      MockRead("HTTP/1.0 200 OK\r\n"),
5571      MockRead("Content-Length: 100\r\n\r\n"),
5572      MockRead(SYNCHRONOUS, OK),
5573    };
5574
5575    StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5576                                   data_writes1, arraysize(data_writes1));
5577    session_deps_.socket_factory->AddSocketDataProvider(&data1);
5578
5579    TestCompletionCallback callback1;
5580
5581    int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5582    EXPECT_EQ(ERR_IO_PENDING, rv);
5583
5584    rv = callback1.WaitForResult();
5585    EXPECT_EQ(OK, rv);
5586
5587    const HttpResponseInfo* response = trans->GetResponseInfo();
5588    ASSERT_TRUE(response != NULL);
5589    EXPECT_TRUE(response->auth_challenge.get() == NULL);
5590  }
5591}
5592
5593// Test the ResetStateForRestart() private method.
5594TEST_P(HttpNetworkTransactionTest, ResetStateForRestart) {
5595  // Create a transaction (the dependencies aren't important).
5596  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5597  scoped_ptr<HttpNetworkTransaction> trans(
5598      new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
5599
5600  // Setup some state (which we expect ResetStateForRestart() will clear).
5601  trans->read_buf_ = new IOBuffer(15);
5602  trans->read_buf_len_ = 15;
5603  trans->request_headers_.SetHeader("Authorization", "NTLM");
5604
5605  // Setup state in response_
5606  HttpResponseInfo* response = &trans->response_;
5607  response->auth_challenge = new AuthChallengeInfo();
5608  response->ssl_info.cert_status = static_cast<CertStatus>(-1);  // Nonsensical.
5609  response->response_time = base::Time::Now();
5610  response->was_cached = true;  // (Wouldn't ever actually be true...)
5611
5612  { // Setup state for response_.vary_data
5613    HttpRequestInfo request;
5614    std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
5615    std::replace(temp.begin(), temp.end(), '\n', '\0');
5616    scoped_refptr<HttpResponseHeaders> headers(new HttpResponseHeaders(temp));
5617    request.extra_headers.SetHeader("Foo", "1");
5618    request.extra_headers.SetHeader("bar", "23");
5619    EXPECT_TRUE(response->vary_data.Init(request, *headers.get()));
5620  }
5621
5622  // Cause the above state to be reset.
5623  trans->ResetStateForRestart();
5624
5625  // Verify that the state that needed to be reset, has been reset.
5626  EXPECT_TRUE(trans->read_buf_.get() == NULL);
5627  EXPECT_EQ(0, trans->read_buf_len_);
5628  EXPECT_TRUE(trans->request_headers_.IsEmpty());
5629  EXPECT_TRUE(response->auth_challenge.get() == NULL);
5630  EXPECT_TRUE(response->headers.get() == NULL);
5631  EXPECT_FALSE(response->was_cached);
5632  EXPECT_EQ(0U, response->ssl_info.cert_status);
5633  EXPECT_FALSE(response->vary_data.is_valid());
5634}
5635
5636// Test HTTPS connections to a site with a bad certificate
5637TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificate) {
5638  HttpRequestInfo request;
5639  request.method = "GET";
5640  request.url = GURL("https://www.google.com/");
5641  request.load_flags = 0;
5642
5643  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5644  scoped_ptr<HttpTransaction> trans(
5645      new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
5646
5647  MockWrite data_writes[] = {
5648    MockWrite("GET / HTTP/1.1\r\n"
5649              "Host: www.google.com\r\n"
5650              "Connection: keep-alive\r\n\r\n"),
5651  };
5652
5653  MockRead data_reads[] = {
5654    MockRead("HTTP/1.0 200 OK\r\n"),
5655    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5656    MockRead("Content-Length: 100\r\n\r\n"),
5657    MockRead(SYNCHRONOUS, OK),
5658  };
5659
5660  StaticSocketDataProvider ssl_bad_certificate;
5661  StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5662                                data_writes, arraysize(data_writes));
5663  SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
5664  SSLSocketDataProvider ssl(ASYNC, OK);
5665
5666  session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
5667  session_deps_.socket_factory->AddSocketDataProvider(&data);
5668  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
5669  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
5670
5671  TestCompletionCallback callback;
5672
5673  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5674  EXPECT_EQ(ERR_IO_PENDING, rv);
5675
5676  rv = callback.WaitForResult();
5677  EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
5678
5679  rv = trans->RestartIgnoringLastError(callback.callback());
5680  EXPECT_EQ(ERR_IO_PENDING, rv);
5681
5682  rv = callback.WaitForResult();
5683  EXPECT_EQ(OK, rv);
5684
5685  const HttpResponseInfo* response = trans->GetResponseInfo();
5686
5687  ASSERT_TRUE(response != NULL);
5688  EXPECT_EQ(100, response->headers->GetContentLength());
5689}
5690
5691// Test HTTPS connections to a site with a bad certificate, going through a
5692// proxy
5693TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
5694  session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
5695
5696  HttpRequestInfo request;
5697  request.method = "GET";
5698  request.url = GURL("https://www.google.com/");
5699  request.load_flags = 0;
5700
5701  MockWrite proxy_writes[] = {
5702    MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
5703              "Host: www.google.com\r\n"
5704              "Proxy-Connection: keep-alive\r\n\r\n"),
5705  };
5706
5707  MockRead proxy_reads[] = {
5708    MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
5709    MockRead(SYNCHRONOUS, OK)
5710  };
5711
5712  MockWrite data_writes[] = {
5713    MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
5714              "Host: www.google.com\r\n"
5715              "Proxy-Connection: keep-alive\r\n\r\n"),
5716    MockWrite("GET / HTTP/1.1\r\n"
5717              "Host: www.google.com\r\n"
5718              "Connection: keep-alive\r\n\r\n"),
5719  };
5720
5721  MockRead data_reads[] = {
5722    MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
5723    MockRead("HTTP/1.0 200 OK\r\n"),
5724    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5725    MockRead("Content-Length: 100\r\n\r\n"),
5726    MockRead(SYNCHRONOUS, OK),
5727  };
5728
5729  StaticSocketDataProvider ssl_bad_certificate(
5730      proxy_reads, arraysize(proxy_reads),
5731      proxy_writes, arraysize(proxy_writes));
5732  StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5733                                data_writes, arraysize(data_writes));
5734  SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
5735  SSLSocketDataProvider ssl(ASYNC, OK);
5736
5737  session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
5738  session_deps_.socket_factory->AddSocketDataProvider(&data);
5739  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
5740  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
5741
5742  TestCompletionCallback callback;
5743
5744  for (int i = 0; i < 2; i++) {
5745    session_deps_.socket_factory->ResetNextMockIndexes();
5746
5747    scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5748    scoped_ptr<HttpTransaction> trans(
5749        new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
5750
5751    int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5752    EXPECT_EQ(ERR_IO_PENDING, rv);
5753
5754    rv = callback.WaitForResult();
5755    EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
5756
5757    rv = trans->RestartIgnoringLastError(callback.callback());
5758    EXPECT_EQ(ERR_IO_PENDING, rv);
5759
5760    rv = callback.WaitForResult();
5761    EXPECT_EQ(OK, rv);
5762
5763    const HttpResponseInfo* response = trans->GetResponseInfo();
5764
5765    ASSERT_TRUE(response != NULL);
5766    EXPECT_EQ(100, response->headers->GetContentLength());
5767  }
5768}
5769
5770
5771// Test HTTPS connections to a site, going through an HTTPS proxy
5772TEST_P(HttpNetworkTransactionTest, HTTPSViaHttpsProxy) {
5773  session_deps_.proxy_service.reset(
5774      ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
5775  CapturingNetLog net_log;
5776  session_deps_.net_log = &net_log;
5777
5778  HttpRequestInfo request;
5779  request.method = "GET";
5780  request.url = GURL("https://www.google.com/");
5781  request.load_flags = 0;
5782
5783  MockWrite data_writes[] = {
5784    MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
5785              "Host: www.google.com\r\n"
5786              "Proxy-Connection: keep-alive\r\n\r\n"),
5787    MockWrite("GET / HTTP/1.1\r\n"
5788              "Host: www.google.com\r\n"
5789              "Connection: keep-alive\r\n\r\n"),
5790  };
5791
5792  MockRead data_reads[] = {
5793    MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
5794    MockRead("HTTP/1.1 200 OK\r\n"),
5795    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5796    MockRead("Content-Length: 100\r\n\r\n"),
5797    MockRead(SYNCHRONOUS, OK),
5798  };
5799
5800  StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5801                                data_writes, arraysize(data_writes));
5802  SSLSocketDataProvider proxy_ssl(ASYNC, OK);  // SSL to the proxy
5803  SSLSocketDataProvider tunnel_ssl(ASYNC, OK);  // SSL through the tunnel
5804
5805  session_deps_.socket_factory->AddSocketDataProvider(&data);
5806  session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
5807  session_deps_.socket_factory->AddSSLSocketDataProvider(&tunnel_ssl);
5808
5809  TestCompletionCallback callback;
5810
5811  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5812  scoped_ptr<HttpTransaction> trans(
5813      new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
5814
5815  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5816  EXPECT_EQ(ERR_IO_PENDING, rv);
5817
5818  rv = callback.WaitForResult();
5819  EXPECT_EQ(OK, rv);
5820  const HttpResponseInfo* response = trans->GetResponseInfo();
5821
5822  ASSERT_TRUE(response != NULL);
5823
5824  EXPECT_TRUE(response->headers->IsKeepAlive());
5825  EXPECT_EQ(200, response->headers->response_code());
5826  EXPECT_EQ(100, response->headers->GetContentLength());
5827  EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
5828
5829  LoadTimingInfo load_timing_info;
5830  EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
5831  TestLoadTimingNotReusedWithPac(load_timing_info,
5832                                 CONNECT_TIMING_HAS_SSL_TIMES);
5833}
5834
5835// Test an HTTPS Proxy's ability to redirect a CONNECT request
5836TEST_P(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaHttpsProxy) {
5837  session_deps_.proxy_service.reset(
5838      ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
5839  CapturingNetLog net_log;
5840  session_deps_.net_log = &net_log;
5841
5842  HttpRequestInfo request;
5843  request.method = "GET";
5844  request.url = GURL("https://www.google.com/");
5845  request.load_flags = 0;
5846
5847  MockWrite data_writes[] = {
5848    MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
5849              "Host: www.google.com\r\n"
5850              "Proxy-Connection: keep-alive\r\n\r\n"),
5851  };
5852
5853  MockRead data_reads[] = {
5854    MockRead("HTTP/1.1 302 Redirect\r\n"),
5855    MockRead("Location: http://login.example.com/\r\n"),
5856    MockRead("Content-Length: 0\r\n\r\n"),
5857    MockRead(SYNCHRONOUS, OK),
5858  };
5859
5860  StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5861                                data_writes, arraysize(data_writes));
5862  SSLSocketDataProvider proxy_ssl(ASYNC, OK);  // SSL to the proxy
5863
5864  session_deps_.socket_factory->AddSocketDataProvider(&data);
5865  session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
5866
5867  TestCompletionCallback callback;
5868
5869  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5870  scoped_ptr<HttpTransaction> trans(
5871      new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
5872
5873  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5874  EXPECT_EQ(ERR_IO_PENDING, rv);
5875
5876  rv = callback.WaitForResult();
5877  EXPECT_EQ(OK, rv);
5878  const HttpResponseInfo* response = trans->GetResponseInfo();
5879
5880  ASSERT_TRUE(response != NULL);
5881
5882  EXPECT_EQ(302, response->headers->response_code());
5883  std::string url;
5884  EXPECT_TRUE(response->headers->IsRedirect(&url));
5885  EXPECT_EQ("http://login.example.com/", url);
5886
5887  // In the case of redirects from proxies, HttpNetworkTransaction returns
5888  // timing for the proxy connection instead of the connection to the host,
5889  // and no send / receive times.
5890  // See HttpNetworkTransaction::OnHttpsProxyTunnelResponse.
5891  LoadTimingInfo load_timing_info;
5892  EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
5893
5894  EXPECT_FALSE(load_timing_info.socket_reused);
5895  EXPECT_NE(net::NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
5896
5897  EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null());
5898  EXPECT_LE(load_timing_info.proxy_resolve_start,
5899            load_timing_info.proxy_resolve_end);
5900  EXPECT_LE(load_timing_info.proxy_resolve_end,
5901            load_timing_info.connect_timing.connect_start);
5902  ExpectConnectTimingHasTimes(
5903      load_timing_info.connect_timing,
5904      CONNECT_TIMING_HAS_DNS_TIMES | CONNECT_TIMING_HAS_SSL_TIMES);
5905
5906  EXPECT_TRUE(load_timing_info.send_start.is_null());
5907  EXPECT_TRUE(load_timing_info.send_end.is_null());
5908  EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
5909}
5910
5911// Test an HTTPS (SPDY) Proxy's ability to redirect a CONNECT request
5912TEST_P(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaSpdyProxy) {
5913  session_deps_.proxy_service.reset(
5914      ProxyService::CreateFixed("https://proxy:70"));
5915
5916  HttpRequestInfo request;
5917  request.method = "GET";
5918  request.url = GURL("https://www.google.com/");
5919  request.load_flags = 0;
5920
5921  scoped_ptr<SpdyFrame> conn(spdy_util_.ConstructSpdyConnect(NULL, 0, 1,
5922                                                             LOWEST));
5923  scoped_ptr<SpdyFrame> goaway(
5924      spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
5925  MockWrite data_writes[] = {
5926    CreateMockWrite(*conn.get(), 0, SYNCHRONOUS),
5927    CreateMockWrite(*goaway.get(), 3, SYNCHRONOUS),
5928  };
5929
5930  static const char* const kExtraHeaders[] = {
5931    "location",
5932    "http://login.example.com/",
5933  };
5934  scoped_ptr<SpdyFrame> resp(
5935      spdy_util_.ConstructSpdySynReplyError("302 Redirect", kExtraHeaders,
5936                                 arraysize(kExtraHeaders)/2, 1));
5937  MockRead data_reads[] = {
5938    CreateMockRead(*resp.get(), 1, SYNCHRONOUS),
5939    MockRead(ASYNC, 0, 2),  // EOF
5940  };
5941
5942  DelayedSocketData data(
5943      1,  // wait for one write to finish before reading.
5944      data_reads, arraysize(data_reads),
5945      data_writes, arraysize(data_writes));
5946  SSLSocketDataProvider proxy_ssl(ASYNC, OK);  // SSL to the proxy
5947  proxy_ssl.SetNextProto(GetParam());
5948
5949  session_deps_.socket_factory->AddSocketDataProvider(&data);
5950  session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
5951
5952  TestCompletionCallback callback;
5953
5954  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5955  scoped_ptr<HttpTransaction> trans(
5956      new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
5957
5958  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5959  EXPECT_EQ(ERR_IO_PENDING, rv);
5960
5961  rv = callback.WaitForResult();
5962  EXPECT_EQ(OK, rv);
5963  const HttpResponseInfo* response = trans->GetResponseInfo();
5964
5965  ASSERT_TRUE(response != NULL);
5966
5967  EXPECT_EQ(302, response->headers->response_code());
5968  std::string url;
5969  EXPECT_TRUE(response->headers->IsRedirect(&url));
5970  EXPECT_EQ("http://login.example.com/", url);
5971}
5972
5973// Test that an HTTPS proxy's response to a CONNECT request is filtered.
5974TEST_P(HttpNetworkTransactionTest,
5975       ErrorResponseToHttpsConnectViaHttpsProxy) {
5976  session_deps_.proxy_service.reset(
5977      ProxyService::CreateFixed("https://proxy:70"));
5978
5979  HttpRequestInfo request;
5980  request.method = "GET";
5981  request.url = GURL("https://www.google.com/");
5982  request.load_flags = 0;
5983
5984  MockWrite data_writes[] = {
5985    MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
5986              "Host: www.google.com\r\n"
5987              "Proxy-Connection: keep-alive\r\n\r\n"),
5988  };
5989
5990  MockRead data_reads[] = {
5991    MockRead("HTTP/1.1 404 Not Found\r\n"),
5992    MockRead("Content-Length: 23\r\n\r\n"),
5993    MockRead("The host does not exist"),
5994    MockRead(SYNCHRONOUS, OK),
5995  };
5996
5997  StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5998                                data_writes, arraysize(data_writes));
5999  SSLSocketDataProvider proxy_ssl(ASYNC, OK);  // SSL to the proxy
6000
6001  session_deps_.socket_factory->AddSocketDataProvider(&data);
6002  session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
6003
6004  TestCompletionCallback callback;
6005
6006  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6007  scoped_ptr<HttpTransaction> trans(
6008      new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6009
6010  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6011  EXPECT_EQ(ERR_IO_PENDING, rv);
6012
6013  rv = callback.WaitForResult();
6014  EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
6015
6016  // TODO(ttuttle): Anything else to check here?
6017}
6018
6019// Test that a SPDY proxy's response to a CONNECT request is filtered.
6020TEST_P(HttpNetworkTransactionTest,
6021       ErrorResponseToHttpsConnectViaSpdyProxy) {
6022  session_deps_.proxy_service.reset(
6023     ProxyService::CreateFixed("https://proxy:70"));
6024
6025  HttpRequestInfo request;
6026  request.method = "GET";
6027  request.url = GURL("https://www.google.com/");
6028  request.load_flags = 0;
6029
6030  scoped_ptr<SpdyFrame> conn(spdy_util_.ConstructSpdyConnect(NULL, 0, 1,
6031                                                             LOWEST));
6032  scoped_ptr<SpdyFrame> rst(
6033      spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
6034  MockWrite data_writes[] = {
6035    CreateMockWrite(*conn.get(), 0, SYNCHRONOUS),
6036    CreateMockWrite(*rst.get(), 3, SYNCHRONOUS),
6037  };
6038
6039  static const char* const kExtraHeaders[] = {
6040    "location",
6041    "http://login.example.com/",
6042  };
6043  scoped_ptr<SpdyFrame> resp(
6044      spdy_util_.ConstructSpdySynReplyError("404 Not Found", kExtraHeaders,
6045                                 arraysize(kExtraHeaders)/2, 1));
6046  scoped_ptr<SpdyFrame> body(
6047      spdy_util_.ConstructSpdyBodyFrame(
6048          1, "The host does not exist", 23, true));
6049  MockRead data_reads[] = {
6050    CreateMockRead(*resp.get(), 1, SYNCHRONOUS),
6051    CreateMockRead(*body.get(), 2, SYNCHRONOUS),
6052    MockRead(ASYNC, 0, 4),  // EOF
6053  };
6054
6055  DelayedSocketData data(
6056      1,  // wait for one write to finish before reading.
6057      data_reads, arraysize(data_reads),
6058      data_writes, arraysize(data_writes));
6059  SSLSocketDataProvider proxy_ssl(ASYNC, OK);  // SSL to the proxy
6060  proxy_ssl.SetNextProto(GetParam());
6061
6062  session_deps_.socket_factory->AddSocketDataProvider(&data);
6063  session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
6064
6065  TestCompletionCallback callback;
6066
6067  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6068  scoped_ptr<HttpTransaction> trans(
6069      new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6070
6071  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6072  EXPECT_EQ(ERR_IO_PENDING, rv);
6073
6074  rv = callback.WaitForResult();
6075  EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
6076
6077  // TODO(ttuttle): Anything else to check here?
6078}
6079
6080// Test the request-challenge-retry sequence for basic auth, through
6081// a SPDY proxy over a single SPDY session.
6082TEST_P(HttpNetworkTransactionTest, BasicAuthSpdyProxy) {
6083  HttpRequestInfo request;
6084  request.method = "GET";
6085  request.url = GURL("https://www.google.com/");
6086  // when the no authentication data flag is set.
6087  request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
6088
6089  // Configure against https proxy server "myproxy:70".
6090  session_deps_.proxy_service.reset(
6091      ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70"));
6092  CapturingBoundNetLog log;
6093  session_deps_.net_log = log.bound().net_log();
6094  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6095
6096  // Since we have proxy, should try to establish tunnel.
6097  scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyConnect(NULL, 0, 1,
6098                                                            LOWEST));
6099  scoped_ptr<SpdyFrame> rst(
6100      spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
6101
6102  // After calling trans->RestartWithAuth(), this is the request we should
6103  // be issuing -- the final header line contains the credentials.
6104  const char* const kAuthCredentials[] = {
6105      "proxy-authorization", "Basic Zm9vOmJhcg==",
6106  };
6107  scoped_ptr<SpdyFrame> connect2(spdy_util_.ConstructSpdyConnect(
6108      kAuthCredentials, arraysize(kAuthCredentials) / 2, 3, LOWEST));
6109  // fetch https://www.google.com/ via HTTP
6110  const char get[] = "GET / HTTP/1.1\r\n"
6111    "Host: www.google.com\r\n"
6112    "Connection: keep-alive\r\n\r\n";
6113  scoped_ptr<SpdyFrame> wrapped_get(
6114      spdy_util_.ConstructSpdyBodyFrame(3, get, strlen(get), false));
6115
6116  MockWrite spdy_writes[] = {
6117    CreateMockWrite(*req, 1, ASYNC),
6118    CreateMockWrite(*rst, 4, ASYNC),
6119    CreateMockWrite(*connect2, 5),
6120    CreateMockWrite(*wrapped_get, 8),
6121  };
6122
6123  // The proxy responds to the connect with a 407, using a persistent
6124  // connection.
6125  const char* const kAuthChallenge[] = {
6126    spdy_util_.GetStatusKey(), "407 Proxy Authentication Required",
6127    spdy_util_.GetVersionKey(), "HTTP/1.1",
6128    "proxy-authenticate", "Basic realm=\"MyRealm1\"",
6129  };
6130
6131  scoped_ptr<SpdyFrame> conn_auth_resp(
6132      spdy_util_.ConstructSpdyControlFrame(NULL,
6133                                           0,
6134                                           false,
6135                                           1,
6136                                           LOWEST,
6137                                           SYN_REPLY,
6138                                           CONTROL_FLAG_NONE,
6139                                           kAuthChallenge,
6140                                           arraysize(kAuthChallenge),
6141                                           0));
6142
6143  scoped_ptr<SpdyFrame> conn_resp(
6144      spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
6145  const char resp[] = "HTTP/1.1 200 OK\r\n"
6146      "Content-Length: 5\r\n\r\n";
6147
6148  scoped_ptr<SpdyFrame> wrapped_get_resp(
6149      spdy_util_.ConstructSpdyBodyFrame(3, resp, strlen(resp), false));
6150  scoped_ptr<SpdyFrame> wrapped_body(
6151      spdy_util_.ConstructSpdyBodyFrame(3, "hello", 5, false));
6152  MockRead spdy_reads[] = {
6153    CreateMockRead(*conn_auth_resp, 2, ASYNC),
6154    CreateMockRead(*conn_resp, 6, ASYNC),
6155    CreateMockRead(*wrapped_get_resp, 9, ASYNC),
6156    CreateMockRead(*wrapped_body, 10, ASYNC),
6157    MockRead(ASYNC, OK, 11),  // EOF.  May or may not be read.
6158  };
6159
6160  OrderedSocketData spdy_data(
6161      spdy_reads, arraysize(spdy_reads),
6162      spdy_writes, arraysize(spdy_writes));
6163  session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
6164  // Negotiate SPDY to the proxy
6165  SSLSocketDataProvider proxy(ASYNC, OK);
6166  proxy.SetNextProto(GetParam());
6167  session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
6168  // Vanilla SSL to the server
6169  SSLSocketDataProvider server(ASYNC, OK);
6170  session_deps_.socket_factory->AddSSLSocketDataProvider(&server);
6171
6172  TestCompletionCallback callback1;
6173
6174  scoped_ptr<HttpTransaction> trans(
6175      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6176
6177  int rv = trans->Start(&request, callback1.callback(), log.bound());
6178  EXPECT_EQ(ERR_IO_PENDING, rv);
6179
6180  rv = callback1.WaitForResult();
6181  EXPECT_EQ(OK, rv);
6182  net::CapturingNetLog::CapturedEntryList entries;
6183  log.GetEntries(&entries);
6184  size_t pos = ExpectLogContainsSomewhere(
6185      entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
6186      NetLog::PHASE_NONE);
6187  ExpectLogContainsSomewhere(
6188      entries, pos,
6189      NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
6190      NetLog::PHASE_NONE);
6191
6192  const HttpResponseInfo* response = trans->GetResponseInfo();
6193  ASSERT_TRUE(response != NULL);
6194  ASSERT_FALSE(response->headers.get() == NULL);
6195  EXPECT_EQ(407, response->headers->response_code());
6196  EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
6197  EXPECT_TRUE(response->auth_challenge.get() != NULL);
6198  EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
6199
6200  TestCompletionCallback callback2;
6201
6202  rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar),
6203                              callback2.callback());
6204  EXPECT_EQ(ERR_IO_PENDING, rv);
6205
6206  rv = callback2.WaitForResult();
6207  EXPECT_EQ(OK, rv);
6208
6209  response = trans->GetResponseInfo();
6210  ASSERT_TRUE(response != NULL);
6211
6212  EXPECT_TRUE(response->headers->IsKeepAlive());
6213  EXPECT_EQ(200, response->headers->response_code());
6214  EXPECT_EQ(5, response->headers->GetContentLength());
6215  EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
6216
6217  // The password prompt info should not be set.
6218  EXPECT_TRUE(response->auth_challenge.get() == NULL);
6219
6220  LoadTimingInfo load_timing_info;
6221  EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
6222  TestLoadTimingNotReusedWithPac(load_timing_info,
6223                                 CONNECT_TIMING_HAS_SSL_TIMES);
6224
6225  trans.reset();
6226  session->CloseAllConnections();
6227}
6228
6229// Test that an explicitly trusted SPDY proxy can push a resource from an
6230// origin that is different from that of its associated resource.
6231TEST_P(HttpNetworkTransactionTest, CrossOriginProxyPush) {
6232  HttpRequestInfo request;
6233  HttpRequestInfo push_request;
6234
6235  request.method = "GET";
6236  request.url = GURL("http://www.google.com/");
6237  push_request.method = "GET";
6238  push_request.url = GURL("http://www.another-origin.com/foo.dat");
6239
6240  // Configure against https proxy server "myproxy:70".
6241  session_deps_.proxy_service.reset(
6242      ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70"));
6243  CapturingBoundNetLog log;
6244  session_deps_.net_log = log.bound().net_log();
6245
6246  // Enable cross-origin push.
6247  session_deps_.trusted_spdy_proxy = "myproxy:70";
6248
6249  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6250
6251  scoped_ptr<SpdyFrame> stream1_syn(
6252      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
6253
6254  MockWrite spdy_writes[] = {
6255    CreateMockWrite(*stream1_syn, 1, ASYNC),
6256  };
6257
6258  scoped_ptr<SpdyFrame>
6259      stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
6260
6261  scoped_ptr<SpdyFrame>
6262      stream1_body(spdy_util_.ConstructSpdyBodyFrame(1, true));
6263
6264  scoped_ptr<SpdyFrame>
6265      stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
6266                                    0,
6267                                    2,
6268                                    1,
6269                                    "http://www.another-origin.com/foo.dat"));
6270  const char kPushedData[] = "pushed";
6271  scoped_ptr<SpdyFrame> stream2_body(
6272      spdy_util_.ConstructSpdyBodyFrame(
6273          2, kPushedData, strlen(kPushedData), true));
6274
6275  MockRead spdy_reads[] = {
6276    CreateMockRead(*stream1_reply, 2, ASYNC),
6277    CreateMockRead(*stream2_syn, 3, ASYNC),
6278    CreateMockRead(*stream1_body, 4, ASYNC),
6279    CreateMockRead(*stream2_body, 5, ASYNC),
6280    MockRead(ASYNC, ERR_IO_PENDING, 6),  // Force a pause
6281  };
6282
6283  OrderedSocketData spdy_data(
6284      spdy_reads, arraysize(spdy_reads),
6285      spdy_writes, arraysize(spdy_writes));
6286  session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
6287  // Negotiate SPDY to the proxy
6288  SSLSocketDataProvider proxy(ASYNC, OK);
6289  proxy.SetNextProto(GetParam());
6290  session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
6291
6292  scoped_ptr<HttpTransaction> trans(
6293      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6294  TestCompletionCallback callback;
6295  int rv = trans->Start(&request, callback.callback(), log.bound());
6296  EXPECT_EQ(ERR_IO_PENDING, rv);
6297
6298  rv = callback.WaitForResult();
6299  EXPECT_EQ(OK, rv);
6300  const HttpResponseInfo* response = trans->GetResponseInfo();
6301
6302  scoped_ptr<HttpTransaction> push_trans(
6303      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6304  rv = push_trans->Start(&push_request, callback.callback(), log.bound());
6305  EXPECT_EQ(ERR_IO_PENDING, rv);
6306
6307  rv = callback.WaitForResult();
6308  EXPECT_EQ(OK, rv);
6309  const HttpResponseInfo* push_response = push_trans->GetResponseInfo();
6310
6311  ASSERT_TRUE(response != NULL);
6312  EXPECT_TRUE(response->headers->IsKeepAlive());
6313
6314  EXPECT_EQ(200, response->headers->response_code());
6315  EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
6316
6317  std::string response_data;
6318  rv = ReadTransaction(trans.get(), &response_data);
6319  EXPECT_EQ(OK, rv);
6320  EXPECT_EQ("hello!", response_data);
6321
6322  LoadTimingInfo load_timing_info;
6323  EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
6324  TestLoadTimingNotReusedWithPac(load_timing_info,
6325                                 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
6326
6327  // Verify the pushed stream.
6328  EXPECT_TRUE(push_response->headers.get() != NULL);
6329  EXPECT_EQ(200, push_response->headers->response_code());
6330
6331  rv = ReadTransaction(push_trans.get(), &response_data);
6332  EXPECT_EQ(OK, rv);
6333  EXPECT_EQ("pushed", response_data);
6334
6335  LoadTimingInfo push_load_timing_info;
6336  EXPECT_TRUE(push_trans->GetLoadTimingInfo(&push_load_timing_info));
6337  TestLoadTimingReusedWithPac(push_load_timing_info);
6338  // The transactions should share a socket ID, despite being for different
6339  // origins.
6340  EXPECT_EQ(load_timing_info.socket_log_id,
6341            push_load_timing_info.socket_log_id);
6342
6343  trans.reset();
6344  push_trans.reset();
6345  session->CloseAllConnections();
6346}
6347
6348// Test that an explicitly trusted SPDY proxy cannot push HTTPS content.
6349TEST_P(HttpNetworkTransactionTest, CrossOriginProxyPushCorrectness) {
6350  HttpRequestInfo request;
6351
6352  request.method = "GET";
6353  request.url = GURL("http://www.google.com/");
6354
6355  // Configure against https proxy server "myproxy:70".
6356  session_deps_.proxy_service.reset(
6357      ProxyService::CreateFixed("https://myproxy:70"));
6358  CapturingBoundNetLog log;
6359  session_deps_.net_log = log.bound().net_log();
6360
6361  // Enable cross-origin push.
6362  session_deps_.trusted_spdy_proxy = "myproxy:70";
6363
6364  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6365
6366  scoped_ptr<SpdyFrame> stream1_syn(
6367      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
6368
6369  scoped_ptr<SpdyFrame> push_rst(
6370      spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
6371
6372  MockWrite spdy_writes[] = {
6373    CreateMockWrite(*stream1_syn, 1, ASYNC),
6374    CreateMockWrite(*push_rst, 4),
6375  };
6376
6377  scoped_ptr<SpdyFrame>
6378      stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
6379
6380  scoped_ptr<SpdyFrame>
6381      stream1_body(spdy_util_.ConstructSpdyBodyFrame(1, true));
6382
6383  scoped_ptr<SpdyFrame>
6384      stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
6385                                    0,
6386                                    2,
6387                                    1,
6388                                    "https://www.another-origin.com/foo.dat"));
6389
6390  MockRead spdy_reads[] = {
6391    CreateMockRead(*stream1_reply, 2, ASYNC),
6392    CreateMockRead(*stream2_syn, 3, ASYNC),
6393    CreateMockRead(*stream1_body, 5, ASYNC),
6394    MockRead(ASYNC, ERR_IO_PENDING, 6),  // Force a pause
6395  };
6396
6397  OrderedSocketData spdy_data(
6398      spdy_reads, arraysize(spdy_reads),
6399      spdy_writes, arraysize(spdy_writes));
6400  session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
6401  // Negotiate SPDY to the proxy
6402  SSLSocketDataProvider proxy(ASYNC, OK);
6403  proxy.SetNextProto(GetParam());
6404  session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
6405
6406  scoped_ptr<HttpTransaction> trans(
6407      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6408  TestCompletionCallback callback;
6409  int rv = trans->Start(&request, callback.callback(), log.bound());
6410  EXPECT_EQ(ERR_IO_PENDING, rv);
6411
6412  rv = callback.WaitForResult();
6413  EXPECT_EQ(OK, rv);
6414  const HttpResponseInfo* response = trans->GetResponseInfo();
6415
6416  ASSERT_TRUE(response != NULL);
6417  EXPECT_TRUE(response->headers->IsKeepAlive());
6418
6419  EXPECT_EQ(200, response->headers->response_code());
6420  EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
6421
6422  std::string response_data;
6423  rv = ReadTransaction(trans.get(), &response_data);
6424  EXPECT_EQ(OK, rv);
6425  EXPECT_EQ("hello!", response_data);
6426
6427  trans.reset();
6428  session->CloseAllConnections();
6429}
6430
6431// Test HTTPS connections to a site with a bad certificate, going through an
6432// HTTPS proxy
6433TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificateViaHttpsProxy) {
6434  session_deps_.proxy_service.reset(ProxyService::CreateFixed(
6435      "https://proxy:70"));
6436
6437  HttpRequestInfo request;
6438  request.method = "GET";
6439  request.url = GURL("https://www.google.com/");
6440  request.load_flags = 0;
6441
6442  // Attempt to fetch the URL from a server with a bad cert
6443  MockWrite bad_cert_writes[] = {
6444    MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6445              "Host: www.google.com\r\n"
6446              "Proxy-Connection: keep-alive\r\n\r\n"),
6447  };
6448
6449  MockRead bad_cert_reads[] = {
6450    MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6451    MockRead(SYNCHRONOUS, OK)
6452  };
6453
6454  // Attempt to fetch the URL with a good cert
6455  MockWrite good_data_writes[] = {
6456    MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6457              "Host: www.google.com\r\n"
6458              "Proxy-Connection: keep-alive\r\n\r\n"),
6459    MockWrite("GET / HTTP/1.1\r\n"
6460              "Host: www.google.com\r\n"
6461              "Connection: keep-alive\r\n\r\n"),
6462  };
6463
6464  MockRead good_cert_reads[] = {
6465    MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6466    MockRead("HTTP/1.0 200 OK\r\n"),
6467    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6468    MockRead("Content-Length: 100\r\n\r\n"),
6469    MockRead(SYNCHRONOUS, OK),
6470  };
6471
6472  StaticSocketDataProvider ssl_bad_certificate(
6473      bad_cert_reads, arraysize(bad_cert_reads),
6474      bad_cert_writes, arraysize(bad_cert_writes));
6475  StaticSocketDataProvider data(good_cert_reads, arraysize(good_cert_reads),
6476                                good_data_writes, arraysize(good_data_writes));
6477  SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
6478  SSLSocketDataProvider ssl(ASYNC, OK);
6479
6480  // SSL to the proxy, then CONNECT request, then SSL with bad certificate
6481  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6482  session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
6483  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
6484
6485  // SSL to the proxy, then CONNECT request, then valid SSL certificate
6486  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6487  session_deps_.socket_factory->AddSocketDataProvider(&data);
6488  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6489
6490  TestCompletionCallback callback;
6491
6492  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6493  scoped_ptr<HttpTransaction> trans(
6494      new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6495
6496  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6497  EXPECT_EQ(ERR_IO_PENDING, rv);
6498
6499  rv = callback.WaitForResult();
6500  EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
6501
6502  rv = trans->RestartIgnoringLastError(callback.callback());
6503  EXPECT_EQ(ERR_IO_PENDING, rv);
6504
6505  rv = callback.WaitForResult();
6506  EXPECT_EQ(OK, rv);
6507
6508  const HttpResponseInfo* response = trans->GetResponseInfo();
6509
6510  ASSERT_TRUE(response != NULL);
6511  EXPECT_EQ(100, response->headers->GetContentLength());
6512}
6513
6514TEST_P(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
6515  HttpRequestInfo request;
6516  request.method = "GET";
6517  request.url = GURL("http://www.google.com/");
6518  request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
6519                                  "Chromium Ultra Awesome X Edition");
6520
6521  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6522  scoped_ptr<HttpTransaction> trans(
6523      new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6524
6525  MockWrite data_writes[] = {
6526    MockWrite("GET / HTTP/1.1\r\n"
6527              "Host: www.google.com\r\n"
6528              "Connection: keep-alive\r\n"
6529              "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
6530  };
6531
6532  // Lastly, the server responds with the actual content.
6533  MockRead data_reads[] = {
6534    MockRead("HTTP/1.0 200 OK\r\n"),
6535    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6536    MockRead("Content-Length: 100\r\n\r\n"),
6537    MockRead(SYNCHRONOUS, OK),
6538  };
6539
6540  StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6541                                data_writes, arraysize(data_writes));
6542  session_deps_.socket_factory->AddSocketDataProvider(&data);
6543
6544  TestCompletionCallback callback;
6545
6546  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6547  EXPECT_EQ(ERR_IO_PENDING, rv);
6548
6549  rv = callback.WaitForResult();
6550  EXPECT_EQ(OK, rv);
6551}
6552
6553TEST_P(HttpNetworkTransactionTest, BuildRequest_UserAgentOverTunnel) {
6554  HttpRequestInfo request;
6555  request.method = "GET";
6556  request.url = GURL("https://www.google.com/");
6557  request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
6558                                  "Chromium Ultra Awesome X Edition");
6559
6560  session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
6561  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6562  scoped_ptr<HttpTransaction> trans(
6563      new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6564
6565  MockWrite data_writes[] = {
6566    MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6567              "Host: www.google.com\r\n"
6568              "Proxy-Connection: keep-alive\r\n"
6569              "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
6570  };
6571  MockRead data_reads[] = {
6572    // Return an error, so the transaction stops here (this test isn't
6573    // interested in the rest).
6574    MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
6575    MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6576    MockRead("Proxy-Connection: close\r\n\r\n"),
6577  };
6578
6579  StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6580                                data_writes, arraysize(data_writes));
6581  session_deps_.socket_factory->AddSocketDataProvider(&data);
6582
6583  TestCompletionCallback callback;
6584
6585  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6586  EXPECT_EQ(ERR_IO_PENDING, rv);
6587
6588  rv = callback.WaitForResult();
6589  EXPECT_EQ(OK, rv);
6590}
6591
6592TEST_P(HttpNetworkTransactionTest, BuildRequest_Referer) {
6593  HttpRequestInfo request;
6594  request.method = "GET";
6595  request.url = GURL("http://www.google.com/");
6596  request.load_flags = 0;
6597  request.extra_headers.SetHeader(HttpRequestHeaders::kReferer,
6598                                  "http://the.previous.site.com/");
6599
6600  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6601  scoped_ptr<HttpTransaction> trans(
6602      new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6603
6604  MockWrite data_writes[] = {
6605    MockWrite("GET / HTTP/1.1\r\n"
6606              "Host: www.google.com\r\n"
6607              "Connection: keep-alive\r\n"
6608              "Referer: http://the.previous.site.com/\r\n\r\n"),
6609  };
6610
6611  // Lastly, the server responds with the actual content.
6612  MockRead data_reads[] = {
6613    MockRead("HTTP/1.0 200 OK\r\n"),
6614    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6615    MockRead("Content-Length: 100\r\n\r\n"),
6616    MockRead(SYNCHRONOUS, OK),
6617  };
6618
6619  StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6620                                data_writes, arraysize(data_writes));
6621  session_deps_.socket_factory->AddSocketDataProvider(&data);
6622
6623  TestCompletionCallback callback;
6624
6625  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6626  EXPECT_EQ(ERR_IO_PENDING, rv);
6627
6628  rv = callback.WaitForResult();
6629  EXPECT_EQ(OK, rv);
6630}
6631
6632TEST_P(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
6633  HttpRequestInfo request;
6634  request.method = "POST";
6635  request.url = GURL("http://www.google.com/");
6636
6637  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6638  scoped_ptr<HttpTransaction> trans(
6639      new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6640
6641  MockWrite data_writes[] = {
6642    MockWrite("POST / HTTP/1.1\r\n"
6643              "Host: www.google.com\r\n"
6644              "Connection: keep-alive\r\n"
6645              "Content-Length: 0\r\n\r\n"),
6646  };
6647
6648  // Lastly, the server responds with the actual content.
6649  MockRead data_reads[] = {
6650    MockRead("HTTP/1.0 200 OK\r\n"),
6651    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6652    MockRead("Content-Length: 100\r\n\r\n"),
6653    MockRead(SYNCHRONOUS, OK),
6654  };
6655
6656  StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6657                                data_writes, arraysize(data_writes));
6658  session_deps_.socket_factory->AddSocketDataProvider(&data);
6659
6660  TestCompletionCallback callback;
6661
6662  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6663  EXPECT_EQ(ERR_IO_PENDING, rv);
6664
6665  rv = callback.WaitForResult();
6666  EXPECT_EQ(OK, rv);
6667}
6668
6669TEST_P(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
6670  HttpRequestInfo request;
6671  request.method = "PUT";
6672  request.url = GURL("http://www.google.com/");
6673
6674  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6675  scoped_ptr<HttpTransaction> trans(
6676      new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6677
6678  MockWrite data_writes[] = {
6679    MockWrite("PUT / HTTP/1.1\r\n"
6680              "Host: www.google.com\r\n"
6681              "Connection: keep-alive\r\n"
6682              "Content-Length: 0\r\n\r\n"),
6683  };
6684
6685  // Lastly, the server responds with the actual content.
6686  MockRead data_reads[] = {
6687    MockRead("HTTP/1.0 200 OK\r\n"),
6688    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6689    MockRead("Content-Length: 100\r\n\r\n"),
6690    MockRead(SYNCHRONOUS, OK),
6691  };
6692
6693  StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6694                                data_writes, arraysize(data_writes));
6695  session_deps_.socket_factory->AddSocketDataProvider(&data);
6696
6697  TestCompletionCallback callback;
6698
6699  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6700  EXPECT_EQ(ERR_IO_PENDING, rv);
6701
6702  rv = callback.WaitForResult();
6703  EXPECT_EQ(OK, rv);
6704}
6705
6706TEST_P(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
6707  HttpRequestInfo request;
6708  request.method = "HEAD";
6709  request.url = GURL("http://www.google.com/");
6710
6711  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6712  scoped_ptr<HttpTransaction> trans(
6713      new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6714
6715  MockWrite data_writes[] = {
6716    MockWrite("HEAD / HTTP/1.1\r\n"
6717              "Host: www.google.com\r\n"
6718              "Connection: keep-alive\r\n"
6719              "Content-Length: 0\r\n\r\n"),
6720  };
6721
6722  // Lastly, the server responds with the actual content.
6723  MockRead data_reads[] = {
6724    MockRead("HTTP/1.0 200 OK\r\n"),
6725    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6726    MockRead("Content-Length: 100\r\n\r\n"),
6727    MockRead(SYNCHRONOUS, OK),
6728  };
6729
6730  StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6731                                data_writes, arraysize(data_writes));
6732  session_deps_.socket_factory->AddSocketDataProvider(&data);
6733
6734  TestCompletionCallback callback;
6735
6736  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6737  EXPECT_EQ(ERR_IO_PENDING, rv);
6738
6739  rv = callback.WaitForResult();
6740  EXPECT_EQ(OK, rv);
6741}
6742
6743TEST_P(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
6744  HttpRequestInfo request;
6745  request.method = "GET";
6746  request.url = GURL("http://www.google.com/");
6747  request.load_flags = LOAD_BYPASS_CACHE;
6748
6749  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6750  scoped_ptr<HttpTransaction> trans(
6751      new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6752
6753  MockWrite data_writes[] = {
6754    MockWrite("GET / HTTP/1.1\r\n"
6755              "Host: www.google.com\r\n"
6756              "Connection: keep-alive\r\n"
6757              "Pragma: no-cache\r\n"
6758              "Cache-Control: no-cache\r\n\r\n"),
6759  };
6760
6761  // Lastly, the server responds with the actual content.
6762  MockRead data_reads[] = {
6763    MockRead("HTTP/1.0 200 OK\r\n"),
6764    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6765    MockRead("Content-Length: 100\r\n\r\n"),
6766    MockRead(SYNCHRONOUS, OK),
6767  };
6768
6769  StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6770                                data_writes, arraysize(data_writes));
6771  session_deps_.socket_factory->AddSocketDataProvider(&data);
6772
6773  TestCompletionCallback callback;
6774
6775  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6776  EXPECT_EQ(ERR_IO_PENDING, rv);
6777
6778  rv = callback.WaitForResult();
6779  EXPECT_EQ(OK, rv);
6780}
6781
6782TEST_P(HttpNetworkTransactionTest,
6783       BuildRequest_CacheControlValidateCache) {
6784  HttpRequestInfo request;
6785  request.method = "GET";
6786  request.url = GURL("http://www.google.com/");
6787  request.load_flags = LOAD_VALIDATE_CACHE;
6788
6789  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6790  scoped_ptr<HttpTransaction> trans(
6791      new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6792
6793  MockWrite data_writes[] = {
6794    MockWrite("GET / HTTP/1.1\r\n"
6795              "Host: www.google.com\r\n"
6796              "Connection: keep-alive\r\n"
6797              "Cache-Control: max-age=0\r\n\r\n"),
6798  };
6799
6800  // Lastly, the server responds with the actual content.
6801  MockRead data_reads[] = {
6802    MockRead("HTTP/1.0 200 OK\r\n"),
6803    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6804    MockRead("Content-Length: 100\r\n\r\n"),
6805    MockRead(SYNCHRONOUS, OK),
6806  };
6807
6808  StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6809                                data_writes, arraysize(data_writes));
6810  session_deps_.socket_factory->AddSocketDataProvider(&data);
6811
6812  TestCompletionCallback callback;
6813
6814  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6815  EXPECT_EQ(ERR_IO_PENDING, rv);
6816
6817  rv = callback.WaitForResult();
6818  EXPECT_EQ(OK, rv);
6819}
6820
6821TEST_P(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
6822  HttpRequestInfo request;
6823  request.method = "GET";
6824  request.url = GURL("http://www.google.com/");
6825  request.extra_headers.SetHeader("FooHeader", "Bar");
6826
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("GET / HTTP/1.1\r\n"
6833              "Host: www.google.com\r\n"
6834              "Connection: keep-alive\r\n"
6835              "FooHeader: Bar\r\n\r\n"),
6836  };
6837
6838  // Lastly, the server responds with the actual content.
6839  MockRead data_reads[] = {
6840    MockRead("HTTP/1.0 200 OK\r\n"),
6841    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6842    MockRead("Content-Length: 100\r\n\r\n"),
6843    MockRead(SYNCHRONOUS, OK),
6844  };
6845
6846  StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6847                                data_writes, arraysize(data_writes));
6848  session_deps_.socket_factory->AddSocketDataProvider(&data);
6849
6850  TestCompletionCallback callback;
6851
6852  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6853  EXPECT_EQ(ERR_IO_PENDING, rv);
6854
6855  rv = callback.WaitForResult();
6856  EXPECT_EQ(OK, rv);
6857}
6858
6859TEST_P(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) {
6860  HttpRequestInfo request;
6861  request.method = "GET";
6862  request.url = GURL("http://www.google.com/");
6863  request.extra_headers.SetHeader("referer", "www.foo.com");
6864  request.extra_headers.SetHeader("hEllo", "Kitty");
6865  request.extra_headers.SetHeader("FoO", "bar");
6866
6867  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6868  scoped_ptr<HttpTransaction> trans(
6869      new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6870
6871  MockWrite data_writes[] = {
6872    MockWrite("GET / HTTP/1.1\r\n"
6873              "Host: www.google.com\r\n"
6874              "Connection: keep-alive\r\n"
6875              "referer: www.foo.com\r\n"
6876              "hEllo: Kitty\r\n"
6877              "FoO: bar\r\n\r\n"),
6878  };
6879
6880  // Lastly, the server responds with the actual content.
6881  MockRead data_reads[] = {
6882    MockRead("HTTP/1.0 200 OK\r\n"),
6883    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6884    MockRead("Content-Length: 100\r\n\r\n"),
6885    MockRead(SYNCHRONOUS, OK),
6886  };
6887
6888  StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6889                                data_writes, arraysize(data_writes));
6890  session_deps_.socket_factory->AddSocketDataProvider(&data);
6891
6892  TestCompletionCallback callback;
6893
6894  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6895  EXPECT_EQ(ERR_IO_PENDING, rv);
6896
6897  rv = callback.WaitForResult();
6898  EXPECT_EQ(OK, rv);
6899}
6900
6901TEST_P(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
6902  HttpRequestInfo request;
6903  request.method = "GET";
6904  request.url = GURL("http://www.google.com/");
6905  request.load_flags = 0;
6906
6907  session_deps_.proxy_service.reset(
6908      ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080"));
6909  CapturingNetLog net_log;
6910  session_deps_.net_log = &net_log;
6911
6912  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6913  scoped_ptr<HttpTransaction> trans(
6914      new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6915
6916  char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
6917  char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
6918
6919  MockWrite data_writes[] = {
6920    MockWrite(ASYNC, write_buffer, arraysize(write_buffer)),
6921    MockWrite("GET / HTTP/1.1\r\n"
6922              "Host: www.google.com\r\n"
6923              "Connection: keep-alive\r\n\r\n")
6924  };
6925
6926  MockRead data_reads[] = {
6927    MockRead(ASYNC, read_buffer, arraysize(read_buffer)),
6928    MockRead("HTTP/1.0 200 OK\r\n"),
6929    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
6930    MockRead("Payload"),
6931    MockRead(SYNCHRONOUS, OK)
6932  };
6933
6934  StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6935                                data_writes, arraysize(data_writes));
6936  session_deps_.socket_factory->AddSocketDataProvider(&data);
6937
6938  TestCompletionCallback callback;
6939
6940  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6941  EXPECT_EQ(ERR_IO_PENDING, rv);
6942
6943  rv = callback.WaitForResult();
6944  EXPECT_EQ(OK, rv);
6945
6946  const HttpResponseInfo* response = trans->GetResponseInfo();
6947  ASSERT_TRUE(response != NULL);
6948
6949  LoadTimingInfo load_timing_info;
6950  EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
6951  TestLoadTimingNotReusedWithPac(load_timing_info,
6952                                 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
6953
6954  std::string response_text;
6955  rv = ReadTransaction(trans.get(), &response_text);
6956  EXPECT_EQ(OK, rv);
6957  EXPECT_EQ("Payload", response_text);
6958}
6959
6960TEST_P(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
6961  HttpRequestInfo request;
6962  request.method = "GET";
6963  request.url = GURL("https://www.google.com/");
6964  request.load_flags = 0;
6965
6966  session_deps_.proxy_service.reset(
6967      ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080"));
6968  CapturingNetLog net_log;
6969  session_deps_.net_log = &net_log;
6970
6971  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6972  scoped_ptr<HttpTransaction> trans(
6973      new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6974
6975  unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
6976  unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
6977
6978  MockWrite data_writes[] = {
6979    MockWrite(ASYNC, reinterpret_cast<char*>(write_buffer),
6980              arraysize(write_buffer)),
6981    MockWrite("GET / HTTP/1.1\r\n"
6982              "Host: www.google.com\r\n"
6983              "Connection: keep-alive\r\n\r\n")
6984  };
6985
6986  MockRead data_reads[] = {
6987    MockRead(ASYNC, reinterpret_cast<char*>(read_buffer),
6988             arraysize(read_buffer)),
6989    MockRead("HTTP/1.0 200 OK\r\n"),
6990    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
6991    MockRead("Payload"),
6992    MockRead(SYNCHRONOUS, OK)
6993  };
6994
6995  StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6996                                data_writes, arraysize(data_writes));
6997  session_deps_.socket_factory->AddSocketDataProvider(&data);
6998
6999  SSLSocketDataProvider ssl(ASYNC, OK);
7000  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7001
7002  TestCompletionCallback callback;
7003
7004  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7005  EXPECT_EQ(ERR_IO_PENDING, rv);
7006
7007  rv = callback.WaitForResult();
7008  EXPECT_EQ(OK, rv);
7009
7010  LoadTimingInfo load_timing_info;
7011  EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7012  TestLoadTimingNotReusedWithPac(load_timing_info,
7013                                 CONNECT_TIMING_HAS_SSL_TIMES);
7014
7015  const HttpResponseInfo* response = trans->GetResponseInfo();
7016  ASSERT_TRUE(response != NULL);
7017
7018  std::string response_text;
7019  rv = ReadTransaction(trans.get(), &response_text);
7020  EXPECT_EQ(OK, rv);
7021  EXPECT_EQ("Payload", response_text);
7022}
7023
7024TEST_P(HttpNetworkTransactionTest, SOCKS4_HTTP_GET_no_PAC) {
7025  HttpRequestInfo request;
7026  request.method = "GET";
7027  request.url = GURL("http://www.google.com/");
7028  request.load_flags = 0;
7029
7030  session_deps_.proxy_service.reset(
7031      ProxyService::CreateFixed("socks4://myproxy:1080"));
7032  CapturingNetLog net_log;
7033  session_deps_.net_log = &net_log;
7034
7035  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7036  scoped_ptr<HttpTransaction> trans(
7037      new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
7038
7039  char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
7040  char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7041
7042  MockWrite data_writes[] = {
7043    MockWrite(ASYNC, write_buffer, arraysize(write_buffer)),
7044    MockWrite("GET / HTTP/1.1\r\n"
7045              "Host: www.google.com\r\n"
7046              "Connection: keep-alive\r\n\r\n")
7047  };
7048
7049  MockRead data_reads[] = {
7050    MockRead(ASYNC, read_buffer, arraysize(read_buffer)),
7051    MockRead("HTTP/1.0 200 OK\r\n"),
7052    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7053    MockRead("Payload"),
7054    MockRead(SYNCHRONOUS, OK)
7055  };
7056
7057  StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7058                                data_writes, arraysize(data_writes));
7059  session_deps_.socket_factory->AddSocketDataProvider(&data);
7060
7061  TestCompletionCallback callback;
7062
7063  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7064  EXPECT_EQ(ERR_IO_PENDING, rv);
7065
7066  rv = callback.WaitForResult();
7067  EXPECT_EQ(OK, rv);
7068
7069  const HttpResponseInfo* response = trans->GetResponseInfo();
7070  ASSERT_TRUE(response != NULL);
7071
7072  LoadTimingInfo load_timing_info;
7073  EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7074  TestLoadTimingNotReused(load_timing_info,
7075                          CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
7076
7077  std::string response_text;
7078  rv = ReadTransaction(trans.get(), &response_text);
7079  EXPECT_EQ(OK, rv);
7080  EXPECT_EQ("Payload", response_text);
7081}
7082
7083TEST_P(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
7084  HttpRequestInfo request;
7085  request.method = "GET";
7086  request.url = GURL("http://www.google.com/");
7087  request.load_flags = 0;
7088
7089  session_deps_.proxy_service.reset(
7090      ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080"));
7091  CapturingNetLog net_log;
7092  session_deps_.net_log = &net_log;
7093
7094  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7095  scoped_ptr<HttpTransaction> trans(
7096      new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
7097
7098  const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
7099  const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
7100  const char kSOCKS5OkRequest[] = {
7101    0x05,  // Version
7102    0x01,  // Command (CONNECT)
7103    0x00,  // Reserved.
7104    0x03,  // Address type (DOMAINNAME).
7105    0x0E,  // Length of domain (14)
7106    // Domain string:
7107    'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
7108    0x00, 0x50,  // 16-bit port (80)
7109  };
7110  const char kSOCKS5OkResponse[] =
7111      { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
7112
7113  MockWrite data_writes[] = {
7114    MockWrite(ASYNC, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
7115    MockWrite(ASYNC, kSOCKS5OkRequest, arraysize(kSOCKS5OkRequest)),
7116    MockWrite("GET / HTTP/1.1\r\n"
7117              "Host: www.google.com\r\n"
7118              "Connection: keep-alive\r\n\r\n")
7119  };
7120
7121  MockRead data_reads[] = {
7122    MockRead(ASYNC, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
7123    MockRead(ASYNC, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
7124    MockRead("HTTP/1.0 200 OK\r\n"),
7125    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7126    MockRead("Payload"),
7127    MockRead(SYNCHRONOUS, OK)
7128  };
7129
7130  StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7131                                data_writes, arraysize(data_writes));
7132  session_deps_.socket_factory->AddSocketDataProvider(&data);
7133
7134  TestCompletionCallback callback;
7135
7136  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7137  EXPECT_EQ(ERR_IO_PENDING, rv);
7138
7139  rv = callback.WaitForResult();
7140  EXPECT_EQ(OK, rv);
7141
7142  const HttpResponseInfo* response = trans->GetResponseInfo();
7143  ASSERT_TRUE(response != NULL);
7144
7145  LoadTimingInfo load_timing_info;
7146  EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7147  TestLoadTimingNotReusedWithPac(load_timing_info,
7148                                 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
7149
7150  std::string response_text;
7151  rv = ReadTransaction(trans.get(), &response_text);
7152  EXPECT_EQ(OK, rv);
7153  EXPECT_EQ("Payload", response_text);
7154}
7155
7156TEST_P(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
7157  HttpRequestInfo request;
7158  request.method = "GET";
7159  request.url = GURL("https://www.google.com/");
7160  request.load_flags = 0;
7161
7162  session_deps_.proxy_service.reset(
7163      ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080"));
7164  CapturingNetLog net_log;
7165  session_deps_.net_log = &net_log;
7166
7167  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7168  scoped_ptr<HttpTransaction> trans(
7169      new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
7170
7171  const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
7172  const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
7173  const unsigned char kSOCKS5OkRequest[] = {
7174    0x05,  // Version
7175    0x01,  // Command (CONNECT)
7176    0x00,  // Reserved.
7177    0x03,  // Address type (DOMAINNAME).
7178    0x0E,  // Length of domain (14)
7179    // Domain string:
7180    'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
7181    0x01, 0xBB,  // 16-bit port (443)
7182  };
7183
7184  const char kSOCKS5OkResponse[] =
7185      { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
7186
7187  MockWrite data_writes[] = {
7188    MockWrite(ASYNC, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
7189    MockWrite(ASYNC, reinterpret_cast<const char*>(kSOCKS5OkRequest),
7190              arraysize(kSOCKS5OkRequest)),
7191    MockWrite("GET / HTTP/1.1\r\n"
7192              "Host: www.google.com\r\n"
7193              "Connection: keep-alive\r\n\r\n")
7194  };
7195
7196  MockRead data_reads[] = {
7197    MockRead(ASYNC, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
7198    MockRead(ASYNC, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
7199    MockRead("HTTP/1.0 200 OK\r\n"),
7200    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7201    MockRead("Payload"),
7202    MockRead(SYNCHRONOUS, OK)
7203  };
7204
7205  StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7206                                data_writes, arraysize(data_writes));
7207  session_deps_.socket_factory->AddSocketDataProvider(&data);
7208
7209  SSLSocketDataProvider ssl(ASYNC, OK);
7210  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7211
7212  TestCompletionCallback callback;
7213
7214  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7215  EXPECT_EQ(ERR_IO_PENDING, rv);
7216
7217  rv = callback.WaitForResult();
7218  EXPECT_EQ(OK, rv);
7219
7220  const HttpResponseInfo* response = trans->GetResponseInfo();
7221  ASSERT_TRUE(response != NULL);
7222
7223  LoadTimingInfo load_timing_info;
7224  EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7225  TestLoadTimingNotReusedWithPac(load_timing_info,
7226                                 CONNECT_TIMING_HAS_SSL_TIMES);
7227
7228  std::string response_text;
7229  rv = ReadTransaction(trans.get(), &response_text);
7230  EXPECT_EQ(OK, rv);
7231  EXPECT_EQ("Payload", response_text);
7232}
7233
7234namespace {
7235
7236// Tests that for connection endpoints the group names are correctly set.
7237
7238struct GroupNameTest {
7239  std::string proxy_server;
7240  std::string url;
7241  std::string expected_group_name;
7242  bool ssl;
7243};
7244
7245scoped_refptr<HttpNetworkSession> SetupSessionForGroupNameTests(
7246    NextProto next_proto,
7247    SpdySessionDependencies* session_deps_) {
7248  scoped_refptr<HttpNetworkSession> session(CreateSession(session_deps_));
7249
7250  base::WeakPtr<HttpServerProperties> http_server_properties =
7251      session->http_server_properties();
7252  http_server_properties->SetAlternateProtocol(
7253      HostPortPair("host.with.alternate", 80), 443,
7254      AlternateProtocolFromNextProto(next_proto));
7255
7256  return session;
7257}
7258
7259int GroupNameTransactionHelper(
7260    const std::string& url,
7261    const scoped_refptr<HttpNetworkSession>& session) {
7262  HttpRequestInfo request;
7263  request.method = "GET";
7264  request.url = GURL(url);
7265  request.load_flags = 0;
7266
7267  scoped_ptr<HttpTransaction> trans(
7268      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7269
7270  TestCompletionCallback callback;
7271
7272  // We do not complete this request, the dtor will clean the transaction up.
7273  return trans->Start(&request, callback.callback(), BoundNetLog());
7274}
7275
7276}  // namespace
7277
7278TEST_P(HttpNetworkTransactionTest, GroupNameForDirectConnections) {
7279  const GroupNameTest tests[] = {
7280    {
7281      "",  // unused
7282      "http://www.google.com/direct",
7283      "www.google.com:80",
7284      false,
7285    },
7286    {
7287      "",  // unused
7288      "http://[2001:1418:13:1::25]/direct",
7289      "[2001:1418:13:1::25]:80",
7290      false,
7291    },
7292
7293    // SSL Tests
7294    {
7295      "",  // unused
7296      "https://www.google.com/direct_ssl",
7297      "ssl/www.google.com:443",
7298      true,
7299    },
7300    {
7301      "",  // unused
7302      "https://[2001:1418:13:1::25]/direct",
7303      "ssl/[2001:1418:13:1::25]:443",
7304      true,
7305    },
7306    {
7307      "",  // unused
7308      "http://host.with.alternate/direct",
7309      "ssl/host.with.alternate:443",
7310      true,
7311    },
7312  };
7313
7314  HttpStreamFactory::set_use_alternate_protocols(true);
7315
7316  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
7317    session_deps_.proxy_service.reset(
7318        ProxyService::CreateFixed(tests[i].proxy_server));
7319    scoped_refptr<HttpNetworkSession> session(
7320        SetupSessionForGroupNameTests(GetParam(), &session_deps_));
7321
7322    HttpNetworkSessionPeer peer(session);
7323    CaptureGroupNameTransportSocketPool* transport_conn_pool =
7324        new CaptureGroupNameTransportSocketPool(NULL, NULL);
7325    CaptureGroupNameSSLSocketPool* ssl_conn_pool =
7326        new CaptureGroupNameSSLSocketPool(NULL, NULL);
7327    scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
7328        new MockClientSocketPoolManager);
7329    mock_pool_manager->SetTransportSocketPool(transport_conn_pool);
7330    mock_pool_manager->SetSSLSocketPool(ssl_conn_pool);
7331    peer.SetClientSocketPoolManager(
7332        mock_pool_manager.PassAs<ClientSocketPoolManager>());
7333
7334    EXPECT_EQ(ERR_IO_PENDING,
7335              GroupNameTransactionHelper(tests[i].url, session));
7336    if (tests[i].ssl)
7337      EXPECT_EQ(tests[i].expected_group_name,
7338                ssl_conn_pool->last_group_name_received());
7339    else
7340      EXPECT_EQ(tests[i].expected_group_name,
7341                transport_conn_pool->last_group_name_received());
7342  }
7343
7344}
7345
7346TEST_P(HttpNetworkTransactionTest, GroupNameForHTTPProxyConnections) {
7347  const GroupNameTest tests[] = {
7348    {
7349      "http_proxy",
7350      "http://www.google.com/http_proxy_normal",
7351      "www.google.com:80",
7352      false,
7353    },
7354
7355    // SSL Tests
7356    {
7357      "http_proxy",
7358      "https://www.google.com/http_connect_ssl",
7359      "ssl/www.google.com:443",
7360      true,
7361    },
7362
7363    {
7364      "http_proxy",
7365      "http://host.with.alternate/direct",
7366      "ssl/host.with.alternate:443",
7367      true,
7368    },
7369
7370    {
7371      "http_proxy",
7372      "ftp://ftp.google.com/http_proxy_normal",
7373      "ftp/ftp.google.com:21",
7374      false,
7375    },
7376  };
7377
7378  HttpStreamFactory::set_use_alternate_protocols(true);
7379
7380  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
7381    session_deps_.proxy_service.reset(
7382        ProxyService::CreateFixed(tests[i].proxy_server));
7383    scoped_refptr<HttpNetworkSession> session(
7384        SetupSessionForGroupNameTests(GetParam(), &session_deps_));
7385
7386    HttpNetworkSessionPeer peer(session);
7387
7388    HostPortPair proxy_host("http_proxy", 80);
7389    CaptureGroupNameHttpProxySocketPool* http_proxy_pool =
7390        new CaptureGroupNameHttpProxySocketPool(NULL, NULL);
7391    CaptureGroupNameSSLSocketPool* ssl_conn_pool =
7392        new CaptureGroupNameSSLSocketPool(NULL, NULL);
7393
7394    scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
7395        new MockClientSocketPoolManager);
7396    mock_pool_manager->SetSocketPoolForHTTPProxy(proxy_host, http_proxy_pool);
7397    mock_pool_manager->SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
7398    peer.SetClientSocketPoolManager(
7399        mock_pool_manager.PassAs<ClientSocketPoolManager>());
7400
7401    EXPECT_EQ(ERR_IO_PENDING,
7402              GroupNameTransactionHelper(tests[i].url, session));
7403    if (tests[i].ssl)
7404      EXPECT_EQ(tests[i].expected_group_name,
7405                ssl_conn_pool->last_group_name_received());
7406    else
7407      EXPECT_EQ(tests[i].expected_group_name,
7408                http_proxy_pool->last_group_name_received());
7409  }
7410}
7411
7412TEST_P(HttpNetworkTransactionTest, GroupNameForSOCKSConnections) {
7413  const GroupNameTest tests[] = {
7414    {
7415      "socks4://socks_proxy:1080",
7416      "http://www.google.com/socks4_direct",
7417      "socks4/www.google.com:80",
7418      false,
7419    },
7420    {
7421      "socks5://socks_proxy:1080",
7422      "http://www.google.com/socks5_direct",
7423      "socks5/www.google.com:80",
7424      false,
7425    },
7426
7427    // SSL Tests
7428    {
7429      "socks4://socks_proxy:1080",
7430      "https://www.google.com/socks4_ssl",
7431      "socks4/ssl/www.google.com:443",
7432      true,
7433    },
7434    {
7435      "socks5://socks_proxy:1080",
7436      "https://www.google.com/socks5_ssl",
7437      "socks5/ssl/www.google.com:443",
7438      true,
7439    },
7440
7441    {
7442      "socks4://socks_proxy:1080",
7443      "http://host.with.alternate/direct",
7444      "socks4/ssl/host.with.alternate:443",
7445      true,
7446    },
7447  };
7448
7449  HttpStreamFactory::set_use_alternate_protocols(true);
7450
7451  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
7452    session_deps_.proxy_service.reset(
7453        ProxyService::CreateFixed(tests[i].proxy_server));
7454    scoped_refptr<HttpNetworkSession> session(
7455        SetupSessionForGroupNameTests(GetParam(), &session_deps_));
7456
7457    HttpNetworkSessionPeer peer(session);
7458
7459    HostPortPair proxy_host("socks_proxy", 1080);
7460    CaptureGroupNameSOCKSSocketPool* socks_conn_pool =
7461        new CaptureGroupNameSOCKSSocketPool(NULL, NULL);
7462    CaptureGroupNameSSLSocketPool* ssl_conn_pool =
7463        new CaptureGroupNameSSLSocketPool(NULL, NULL);
7464
7465    scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
7466        new MockClientSocketPoolManager);
7467    mock_pool_manager->SetSocketPoolForSOCKSProxy(proxy_host, socks_conn_pool);
7468    mock_pool_manager->SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
7469    peer.SetClientSocketPoolManager(
7470        mock_pool_manager.PassAs<ClientSocketPoolManager>());
7471
7472    scoped_ptr<HttpTransaction> trans(
7473        new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7474
7475    EXPECT_EQ(ERR_IO_PENDING,
7476              GroupNameTransactionHelper(tests[i].url, session));
7477    if (tests[i].ssl)
7478      EXPECT_EQ(tests[i].expected_group_name,
7479                ssl_conn_pool->last_group_name_received());
7480    else
7481      EXPECT_EQ(tests[i].expected_group_name,
7482                socks_conn_pool->last_group_name_received());
7483  }
7484}
7485
7486TEST_P(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
7487  HttpRequestInfo request;
7488  request.method = "GET";
7489  request.url = GURL("http://www.google.com/");
7490
7491  session_deps_.proxy_service.reset(
7492      ProxyService::CreateFixed("myproxy:70;foobar:80"));
7493
7494  // This simulates failure resolving all hostnames; that means we will fail
7495  // connecting to both proxies (myproxy:70 and foobar:80).
7496  session_deps_.host_resolver->rules()->AddSimulatedFailure("*");
7497
7498  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7499  scoped_ptr<HttpTransaction> trans(
7500      new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
7501
7502  TestCompletionCallback callback;
7503
7504  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7505  EXPECT_EQ(ERR_IO_PENDING, rv);
7506
7507  rv = callback.WaitForResult();
7508  EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED, rv);
7509}
7510
7511// Base test to make sure that when the load flags for a request specify to
7512// bypass the cache, the DNS cache is not used.
7513void HttpNetworkTransactionTest::BypassHostCacheOnRefreshHelper(
7514    int load_flags) {
7515  // Issue a request, asking to bypass the cache(s).
7516  HttpRequestInfo request;
7517  request.method = "GET";
7518  request.load_flags = load_flags;
7519  request.url = GURL("http://www.google.com/");
7520
7521  // Select a host resolver that does caching.
7522  session_deps_.host_resolver.reset(new MockCachingHostResolver);
7523
7524  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7525  scoped_ptr<HttpTransaction> trans(
7526      new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
7527
7528  // Warm up the host cache so it has an entry for "www.google.com".
7529  AddressList addrlist;
7530  TestCompletionCallback callback;
7531  int rv = session_deps_.host_resolver->Resolve(
7532      HostResolver::RequestInfo(HostPortPair("www.google.com", 80)),
7533      DEFAULT_PRIORITY,
7534      &addrlist,
7535      callback.callback(),
7536      NULL,
7537      BoundNetLog());
7538  EXPECT_EQ(ERR_IO_PENDING, rv);
7539  rv = callback.WaitForResult();
7540  EXPECT_EQ(OK, rv);
7541
7542  // Verify that it was added to host cache, by doing a subsequent async lookup
7543  // and confirming it completes synchronously.
7544  rv = session_deps_.host_resolver->Resolve(
7545      HostResolver::RequestInfo(HostPortPair("www.google.com", 80)),
7546      DEFAULT_PRIORITY,
7547      &addrlist,
7548      callback.callback(),
7549      NULL,
7550      BoundNetLog());
7551  ASSERT_EQ(OK, rv);
7552
7553  // Inject a failure the next time that "www.google.com" is resolved. This way
7554  // we can tell if the next lookup hit the cache, or the "network".
7555  // (cache --> success, "network" --> failure).
7556  session_deps_.host_resolver->rules()->AddSimulatedFailure("www.google.com");
7557
7558  // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
7559  // first read -- this won't be reached as the host resolution will fail first.
7560  MockRead data_reads[] = { MockRead(SYNCHRONOUS, ERR_UNEXPECTED) };
7561  StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
7562  session_deps_.socket_factory->AddSocketDataProvider(&data);
7563
7564  // Run the request.
7565  rv = trans->Start(&request, callback.callback(), BoundNetLog());
7566  ASSERT_EQ(ERR_IO_PENDING, rv);
7567  rv = callback.WaitForResult();
7568
7569  // If we bypassed the cache, we would have gotten a failure while resolving
7570  // "www.google.com".
7571  EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
7572}
7573
7574// There are multiple load flags that should trigger the host cache bypass.
7575// Test each in isolation:
7576TEST_P(HttpNetworkTransactionTest, BypassHostCacheOnRefresh1) {
7577  BypassHostCacheOnRefreshHelper(LOAD_BYPASS_CACHE);
7578}
7579
7580TEST_P(HttpNetworkTransactionTest, BypassHostCacheOnRefresh2) {
7581  BypassHostCacheOnRefreshHelper(LOAD_VALIDATE_CACHE);
7582}
7583
7584TEST_P(HttpNetworkTransactionTest, BypassHostCacheOnRefresh3) {
7585  BypassHostCacheOnRefreshHelper(LOAD_DISABLE_CACHE);
7586}
7587
7588// Make sure we can handle an error when writing the request.
7589TEST_P(HttpNetworkTransactionTest, RequestWriteError) {
7590  HttpRequestInfo request;
7591  request.method = "GET";
7592  request.url = GURL("http://www.foo.com/");
7593  request.load_flags = 0;
7594
7595  MockWrite write_failure[] = {
7596    MockWrite(ASYNC, ERR_CONNECTION_RESET),
7597  };
7598  StaticSocketDataProvider data(NULL, 0,
7599                                write_failure, arraysize(write_failure));
7600  session_deps_.socket_factory->AddSocketDataProvider(&data);
7601  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7602
7603  TestCompletionCallback callback;
7604
7605  scoped_ptr<HttpTransaction> trans(
7606      new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
7607
7608  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7609  EXPECT_EQ(ERR_IO_PENDING, rv);
7610
7611  rv = callback.WaitForResult();
7612  EXPECT_EQ(ERR_CONNECTION_RESET, rv);
7613}
7614
7615// Check that a connection closed after the start of the headers finishes ok.
7616TEST_P(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
7617  HttpRequestInfo request;
7618  request.method = "GET";
7619  request.url = GURL("http://www.foo.com/");
7620  request.load_flags = 0;
7621
7622  MockRead data_reads[] = {
7623    MockRead("HTTP/1."),
7624    MockRead(SYNCHRONOUS, OK),
7625  };
7626
7627  StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
7628  session_deps_.socket_factory->AddSocketDataProvider(&data);
7629  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7630
7631  TestCompletionCallback callback;
7632
7633  scoped_ptr<HttpTransaction> trans(
7634      new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
7635
7636  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7637  EXPECT_EQ(ERR_IO_PENDING, rv);
7638
7639  rv = callback.WaitForResult();
7640  EXPECT_EQ(OK, rv);
7641
7642  const HttpResponseInfo* response = trans->GetResponseInfo();
7643  ASSERT_TRUE(response != NULL);
7644
7645  EXPECT_TRUE(response->headers.get() != NULL);
7646  EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
7647
7648  std::string response_data;
7649  rv = ReadTransaction(trans.get(), &response_data);
7650  EXPECT_EQ(OK, rv);
7651  EXPECT_EQ("", response_data);
7652}
7653
7654// Make sure that a dropped connection while draining the body for auth
7655// restart does the right thing.
7656TEST_P(HttpNetworkTransactionTest, DrainResetOK) {
7657  HttpRequestInfo request;
7658  request.method = "GET";
7659  request.url = GURL("http://www.google.com/");
7660  request.load_flags = 0;
7661
7662  MockWrite data_writes1[] = {
7663    MockWrite("GET / HTTP/1.1\r\n"
7664              "Host: www.google.com\r\n"
7665              "Connection: keep-alive\r\n\r\n"),
7666  };
7667
7668  MockRead data_reads1[] = {
7669    MockRead("HTTP/1.1 401 Unauthorized\r\n"),
7670    MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
7671    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7672    MockRead("Content-Length: 14\r\n\r\n"),
7673    MockRead("Unauth"),
7674    MockRead(ASYNC, ERR_CONNECTION_RESET),
7675  };
7676
7677  StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
7678                                 data_writes1, arraysize(data_writes1));
7679  session_deps_.socket_factory->AddSocketDataProvider(&data1);
7680
7681  // After calling trans->RestartWithAuth(), this is the request we should
7682  // be issuing -- the final header line contains the credentials.
7683  MockWrite data_writes2[] = {
7684    MockWrite("GET / HTTP/1.1\r\n"
7685              "Host: www.google.com\r\n"
7686              "Connection: keep-alive\r\n"
7687              "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
7688  };
7689
7690  // Lastly, the server responds with the actual content.
7691  MockRead data_reads2[] = {
7692    MockRead("HTTP/1.1 200 OK\r\n"),
7693    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7694    MockRead("Content-Length: 100\r\n\r\n"),
7695    MockRead(SYNCHRONOUS, OK),
7696  };
7697
7698  StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
7699                                 data_writes2, arraysize(data_writes2));
7700  session_deps_.socket_factory->AddSocketDataProvider(&data2);
7701  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7702
7703  TestCompletionCallback callback1;
7704
7705  scoped_ptr<HttpTransaction> trans(
7706      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7707
7708  int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
7709  EXPECT_EQ(ERR_IO_PENDING, rv);
7710
7711  rv = callback1.WaitForResult();
7712  EXPECT_EQ(OK, rv);
7713
7714  const HttpResponseInfo* response = trans->GetResponseInfo();
7715  ASSERT_TRUE(response != NULL);
7716  EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
7717
7718  TestCompletionCallback callback2;
7719
7720  rv = trans->RestartWithAuth(
7721      AuthCredentials(kFoo, kBar), callback2.callback());
7722  EXPECT_EQ(ERR_IO_PENDING, rv);
7723
7724  rv = callback2.WaitForResult();
7725  EXPECT_EQ(OK, rv);
7726
7727  response = trans->GetResponseInfo();
7728  ASSERT_TRUE(response != NULL);
7729  EXPECT_TRUE(response->auth_challenge.get() == NULL);
7730  EXPECT_EQ(100, response->headers->GetContentLength());
7731}
7732
7733// Test HTTPS connections going through a proxy that sends extra data.
7734TEST_P(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
7735  session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
7736
7737  HttpRequestInfo request;
7738  request.method = "GET";
7739  request.url = GURL("https://www.google.com/");
7740  request.load_flags = 0;
7741
7742  MockRead proxy_reads[] = {
7743    MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
7744    MockRead(SYNCHRONOUS, OK)
7745  };
7746
7747  StaticSocketDataProvider data(proxy_reads, arraysize(proxy_reads), NULL, 0);
7748  SSLSocketDataProvider ssl(ASYNC, OK);
7749
7750  session_deps_.socket_factory->AddSocketDataProvider(&data);
7751  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7752
7753  TestCompletionCallback callback;
7754
7755  session_deps_.socket_factory->ResetNextMockIndexes();
7756
7757  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7758  scoped_ptr<HttpTransaction> trans(
7759      new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
7760
7761  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7762  EXPECT_EQ(ERR_IO_PENDING, rv);
7763
7764  rv = callback.WaitForResult();
7765  EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
7766}
7767
7768TEST_P(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
7769  HttpRequestInfo request;
7770  request.method = "GET";
7771  request.url = GURL("http://www.google.com/");
7772  request.load_flags = 0;
7773
7774  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7775  scoped_ptr<HttpTransaction> trans(
7776      new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
7777
7778  MockRead data_reads[] = {
7779    MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
7780    MockRead(SYNCHRONOUS, OK),
7781  };
7782
7783  StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
7784  session_deps_.socket_factory->AddSocketDataProvider(&data);
7785
7786  TestCompletionCallback callback;
7787
7788  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7789  EXPECT_EQ(ERR_IO_PENDING, rv);
7790
7791  EXPECT_EQ(OK, callback.WaitForResult());
7792
7793  const HttpResponseInfo* response = trans->GetResponseInfo();
7794  ASSERT_TRUE(response != NULL);
7795
7796  EXPECT_TRUE(response->headers.get() != NULL);
7797  EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
7798
7799  std::string response_data;
7800  rv = ReadTransaction(trans.get(), &response_data);
7801  EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH, rv);
7802}
7803
7804TEST_P(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
7805  base::FilePath temp_file_path;
7806  ASSERT_TRUE(base::CreateTemporaryFile(&temp_file_path));
7807  const uint64 kFakeSize = 100000;  // file is actually blank
7808  UploadFileElementReader::ScopedOverridingContentLengthForTests
7809      overriding_content_length(kFakeSize);
7810
7811  ScopedVector<UploadElementReader> element_readers;
7812  element_readers.push_back(
7813      new UploadFileElementReader(base::MessageLoopProxy::current().get(),
7814                                  temp_file_path,
7815                                  0,
7816                                  kuint64max,
7817                                  base::Time()));
7818  UploadDataStream upload_data_stream(element_readers.Pass(), 0);
7819
7820  HttpRequestInfo request;
7821  request.method = "POST";
7822  request.url = GURL("http://www.google.com/upload");
7823  request.upload_data_stream = &upload_data_stream;
7824  request.load_flags = 0;
7825
7826  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7827  scoped_ptr<HttpTransaction> trans(
7828      new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
7829
7830  MockRead data_reads[] = {
7831    MockRead("HTTP/1.0 200 OK\r\n\r\n"),
7832    MockRead("hello world"),
7833    MockRead(SYNCHRONOUS, OK),
7834  };
7835  StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
7836  session_deps_.socket_factory->AddSocketDataProvider(&data);
7837
7838  TestCompletionCallback callback;
7839
7840  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7841  EXPECT_EQ(ERR_IO_PENDING, rv);
7842
7843  rv = callback.WaitForResult();
7844  EXPECT_EQ(OK, rv);
7845
7846  const HttpResponseInfo* response = trans->GetResponseInfo();
7847  ASSERT_TRUE(response != NULL);
7848
7849  EXPECT_TRUE(response->headers.get() != NULL);
7850  EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
7851
7852  std::string response_data;
7853  rv = ReadTransaction(trans.get(), &response_data);
7854  EXPECT_EQ(OK, rv);
7855  EXPECT_EQ("hello world", response_data);
7856
7857  base::DeleteFile(temp_file_path, false);
7858}
7859
7860TEST_P(HttpNetworkTransactionTest, UploadUnreadableFile) {
7861  base::FilePath temp_file;
7862  ASSERT_TRUE(base::CreateTemporaryFile(&temp_file));
7863  std::string temp_file_content("Unreadable file.");
7864  ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_content.c_str(),
7865                                   temp_file_content.length()));
7866  ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
7867
7868  ScopedVector<UploadElementReader> element_readers;
7869  element_readers.push_back(
7870      new UploadFileElementReader(base::MessageLoopProxy::current().get(),
7871                                  temp_file,
7872                                  0,
7873                                  kuint64max,
7874                                  base::Time()));
7875  UploadDataStream upload_data_stream(element_readers.Pass(), 0);
7876
7877  HttpRequestInfo request;
7878  request.method = "POST";
7879  request.url = GURL("http://www.google.com/upload");
7880  request.upload_data_stream = &upload_data_stream;
7881  request.load_flags = 0;
7882
7883  // If we try to upload an unreadable file, the transaction should fail.
7884  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7885  scoped_ptr<HttpTransaction> trans(
7886      new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
7887
7888  StaticSocketDataProvider data(NULL, 0, NULL, 0);
7889  session_deps_.socket_factory->AddSocketDataProvider(&data);
7890
7891  TestCompletionCallback callback;
7892
7893  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7894  EXPECT_EQ(ERR_IO_PENDING, rv);
7895
7896  rv = callback.WaitForResult();
7897  EXPECT_EQ(ERR_ACCESS_DENIED, rv);
7898
7899  const HttpResponseInfo* response = trans->GetResponseInfo();
7900  EXPECT_FALSE(response);
7901
7902  base::DeleteFile(temp_file, false);
7903}
7904
7905TEST_P(HttpNetworkTransactionTest, CancelDuringInitRequestBody) {
7906  class FakeUploadElementReader : public UploadElementReader {
7907   public:
7908    FakeUploadElementReader() {}
7909    virtual ~FakeUploadElementReader() {}
7910
7911    const CompletionCallback& callback() const { return callback_; }
7912
7913    // UploadElementReader overrides:
7914    virtual int Init(const CompletionCallback& callback) OVERRIDE {
7915      callback_ = callback;
7916      return ERR_IO_PENDING;
7917    }
7918    virtual uint64 GetContentLength() const OVERRIDE { return 0; }
7919    virtual uint64 BytesRemaining() const OVERRIDE { return 0; }
7920    virtual int Read(IOBuffer* buf,
7921                     int buf_length,
7922                     const CompletionCallback& callback) OVERRIDE {
7923      return ERR_FAILED;
7924    }
7925
7926   private:
7927    CompletionCallback callback_;
7928  };
7929
7930  FakeUploadElementReader* fake_reader = new FakeUploadElementReader;
7931  ScopedVector<UploadElementReader> element_readers;
7932  element_readers.push_back(fake_reader);
7933  UploadDataStream upload_data_stream(element_readers.Pass(), 0);
7934
7935  HttpRequestInfo request;
7936  request.method = "POST";
7937  request.url = GURL("http://www.google.com/upload");
7938  request.upload_data_stream = &upload_data_stream;
7939  request.load_flags = 0;
7940
7941  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7942  scoped_ptr<HttpTransaction> trans(
7943      new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
7944
7945  StaticSocketDataProvider data;
7946  session_deps_.socket_factory->AddSocketDataProvider(&data);
7947
7948  TestCompletionCallback callback;
7949  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7950  EXPECT_EQ(ERR_IO_PENDING, rv);
7951  base::MessageLoop::current()->RunUntilIdle();
7952
7953  // Transaction is pending on request body initialization.
7954  ASSERT_FALSE(fake_reader->callback().is_null());
7955
7956  // Return Init()'s result after the transaction gets destroyed.
7957  trans.reset();
7958  fake_reader->callback().Run(OK);  // Should not crash.
7959}
7960
7961// Tests that changes to Auth realms are treated like auth rejections.
7962TEST_P(HttpNetworkTransactionTest, ChangeAuthRealms) {
7963
7964  HttpRequestInfo request;
7965  request.method = "GET";
7966  request.url = GURL("http://www.google.com/");
7967  request.load_flags = 0;
7968
7969  // First transaction will request a resource and receive a Basic challenge
7970  // with realm="first_realm".
7971  MockWrite data_writes1[] = {
7972    MockWrite("GET / HTTP/1.1\r\n"
7973              "Host: www.google.com\r\n"
7974              "Connection: keep-alive\r\n"
7975              "\r\n"),
7976  };
7977  MockRead data_reads1[] = {
7978    MockRead("HTTP/1.1 401 Unauthorized\r\n"
7979             "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
7980             "\r\n"),
7981  };
7982
7983  // After calling trans->RestartWithAuth(), provide an Authentication header
7984  // for first_realm. The server will reject and provide a challenge with
7985  // second_realm.
7986  MockWrite data_writes2[] = {
7987    MockWrite("GET / HTTP/1.1\r\n"
7988              "Host: www.google.com\r\n"
7989              "Connection: keep-alive\r\n"
7990              "Authorization: Basic Zmlyc3Q6YmF6\r\n"
7991              "\r\n"),
7992  };
7993  MockRead data_reads2[] = {
7994    MockRead("HTTP/1.1 401 Unauthorized\r\n"
7995             "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
7996             "\r\n"),
7997  };
7998
7999  // This again fails, and goes back to first_realm. Make sure that the
8000  // entry is removed from cache.
8001  MockWrite data_writes3[] = {
8002    MockWrite("GET / HTTP/1.1\r\n"
8003              "Host: www.google.com\r\n"
8004              "Connection: keep-alive\r\n"
8005              "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
8006              "\r\n"),
8007  };
8008  MockRead data_reads3[] = {
8009    MockRead("HTTP/1.1 401 Unauthorized\r\n"
8010             "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
8011             "\r\n"),
8012  };
8013
8014  // Try one last time (with the correct password) and get the resource.
8015  MockWrite data_writes4[] = {
8016    MockWrite("GET / HTTP/1.1\r\n"
8017              "Host: www.google.com\r\n"
8018              "Connection: keep-alive\r\n"
8019              "Authorization: Basic Zmlyc3Q6YmFy\r\n"
8020              "\r\n"),
8021  };
8022  MockRead data_reads4[] = {
8023    MockRead("HTTP/1.1 200 OK\r\n"
8024             "Content-Type: text/html; charset=iso-8859-1\r\n"
8025             "Content-Length: 5\r\n"
8026             "\r\n"
8027             "hello"),
8028  };
8029
8030  StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
8031                                 data_writes1, arraysize(data_writes1));
8032  StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
8033                                 data_writes2, arraysize(data_writes2));
8034  StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
8035                                 data_writes3, arraysize(data_writes3));
8036  StaticSocketDataProvider data4(data_reads4, arraysize(data_reads4),
8037                                 data_writes4, arraysize(data_writes4));
8038  session_deps_.socket_factory->AddSocketDataProvider(&data1);
8039  session_deps_.socket_factory->AddSocketDataProvider(&data2);
8040  session_deps_.socket_factory->AddSocketDataProvider(&data3);
8041  session_deps_.socket_factory->AddSocketDataProvider(&data4);
8042
8043  TestCompletionCallback callback1;
8044
8045  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8046  scoped_ptr<HttpTransaction> trans(
8047      new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
8048
8049  // Issue the first request with Authorize headers. There should be a
8050  // password prompt for first_realm waiting to be filled in after the
8051  // transaction completes.
8052  int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
8053  EXPECT_EQ(ERR_IO_PENDING, rv);
8054  rv = callback1.WaitForResult();
8055  EXPECT_EQ(OK, rv);
8056  const HttpResponseInfo* response = trans->GetResponseInfo();
8057  ASSERT_TRUE(response != NULL);
8058  const AuthChallengeInfo* challenge = response->auth_challenge.get();
8059  ASSERT_FALSE(challenge == NULL);
8060  EXPECT_FALSE(challenge->is_proxy);
8061  EXPECT_EQ("www.google.com:80", challenge->challenger.ToString());
8062  EXPECT_EQ("first_realm", challenge->realm);
8063  EXPECT_EQ("basic", challenge->scheme);
8064
8065  // Issue the second request with an incorrect password. There should be a
8066  // password prompt for second_realm waiting to be filled in after the
8067  // transaction completes.
8068  TestCompletionCallback callback2;
8069  rv = trans->RestartWithAuth(
8070      AuthCredentials(kFirst, kBaz), callback2.callback());
8071  EXPECT_EQ(ERR_IO_PENDING, rv);
8072  rv = callback2.WaitForResult();
8073  EXPECT_EQ(OK, rv);
8074  response = trans->GetResponseInfo();
8075  ASSERT_TRUE(response != NULL);
8076  challenge = response->auth_challenge.get();
8077  ASSERT_FALSE(challenge == NULL);
8078  EXPECT_FALSE(challenge->is_proxy);
8079  EXPECT_EQ("www.google.com:80", challenge->challenger.ToString());
8080  EXPECT_EQ("second_realm", challenge->realm);
8081  EXPECT_EQ("basic", challenge->scheme);
8082
8083  // Issue the third request with another incorrect password. There should be
8084  // a password prompt for first_realm waiting to be filled in. If the password
8085  // prompt is not present, it indicates that the HttpAuthCacheEntry for
8086  // first_realm was not correctly removed.
8087  TestCompletionCallback callback3;
8088  rv = trans->RestartWithAuth(
8089      AuthCredentials(kSecond, kFou), callback3.callback());
8090  EXPECT_EQ(ERR_IO_PENDING, rv);
8091  rv = callback3.WaitForResult();
8092  EXPECT_EQ(OK, rv);
8093  response = trans->GetResponseInfo();
8094  ASSERT_TRUE(response != NULL);
8095  challenge = response->auth_challenge.get();
8096  ASSERT_FALSE(challenge == NULL);
8097  EXPECT_FALSE(challenge->is_proxy);
8098  EXPECT_EQ("www.google.com:80", challenge->challenger.ToString());
8099  EXPECT_EQ("first_realm", challenge->realm);
8100  EXPECT_EQ("basic", challenge->scheme);
8101
8102  // Issue the fourth request with the correct password and username.
8103  TestCompletionCallback callback4;
8104  rv = trans->RestartWithAuth(
8105      AuthCredentials(kFirst, kBar), callback4.callback());
8106  EXPECT_EQ(ERR_IO_PENDING, rv);
8107  rv = callback4.WaitForResult();
8108  EXPECT_EQ(OK, rv);
8109  response = trans->GetResponseInfo();
8110  ASSERT_TRUE(response != NULL);
8111  EXPECT_TRUE(response->auth_challenge.get() == NULL);
8112}
8113
8114TEST_P(HttpNetworkTransactionTest, HonorAlternateProtocolHeader) {
8115  HttpStreamFactory::SetNextProtos(SpdyNextProtos());
8116  HttpStreamFactory::set_use_alternate_protocols(true);
8117
8118  std::string alternate_protocol_http_header =
8119      GetAlternateProtocolHttpHeader();
8120
8121  MockRead data_reads[] = {
8122    MockRead("HTTP/1.1 200 OK\r\n"),
8123    MockRead(alternate_protocol_http_header.c_str()),
8124    MockRead("hello world"),
8125    MockRead(SYNCHRONOUS, OK),
8126  };
8127
8128  HttpRequestInfo request;
8129  request.method = "GET";
8130  request.url = GURL("http://www.google.com/");
8131  request.load_flags = 0;
8132
8133  StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
8134
8135  session_deps_.socket_factory->AddSocketDataProvider(&data);
8136
8137  TestCompletionCallback callback;
8138
8139  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8140  scoped_ptr<HttpTransaction> trans(
8141      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8142
8143  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8144  EXPECT_EQ(ERR_IO_PENDING, rv);
8145
8146  HostPortPair http_host_port_pair("www.google.com", 80);
8147  const HttpServerProperties& http_server_properties =
8148      *session->http_server_properties();
8149  EXPECT_FALSE(
8150      http_server_properties.HasAlternateProtocol(http_host_port_pair));
8151
8152  EXPECT_EQ(OK, callback.WaitForResult());
8153
8154  const HttpResponseInfo* response = trans->GetResponseInfo();
8155  ASSERT_TRUE(response != NULL);
8156  ASSERT_TRUE(response->headers.get() != NULL);
8157  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8158  EXPECT_FALSE(response->was_fetched_via_spdy);
8159  EXPECT_FALSE(response->was_npn_negotiated);
8160
8161  std::string response_data;
8162  ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8163  EXPECT_EQ("hello world", response_data);
8164
8165  ASSERT_TRUE(http_server_properties.HasAlternateProtocol(http_host_port_pair));
8166  const PortAlternateProtocolPair alternate =
8167      http_server_properties.GetAlternateProtocol(http_host_port_pair);
8168  PortAlternateProtocolPair expected_alternate;
8169  expected_alternate.port = 443;
8170  expected_alternate.protocol = AlternateProtocolFromNextProto(GetParam());
8171  EXPECT_TRUE(expected_alternate.Equals(alternate));
8172}
8173
8174TEST_P(HttpNetworkTransactionTest,
8175       MarkBrokenAlternateProtocolAndFallback) {
8176  HttpStreamFactory::set_use_alternate_protocols(true);
8177
8178  HttpRequestInfo request;
8179  request.method = "GET";
8180  request.url = GURL("http://www.google.com/");
8181  request.load_flags = 0;
8182
8183  MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
8184  StaticSocketDataProvider first_data;
8185  first_data.set_connect_data(mock_connect);
8186  session_deps_.socket_factory->AddSocketDataProvider(&first_data);
8187
8188  MockRead data_reads[] = {
8189    MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8190    MockRead("hello world"),
8191    MockRead(ASYNC, OK),
8192  };
8193  StaticSocketDataProvider second_data(
8194      data_reads, arraysize(data_reads), NULL, 0);
8195  session_deps_.socket_factory->AddSocketDataProvider(&second_data);
8196
8197  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8198
8199  base::WeakPtr<HttpServerProperties> http_server_properties =
8200      session->http_server_properties();
8201  // Port must be < 1024, or the header will be ignored (since initial port was
8202  // port 80 (another restricted port).
8203  http_server_properties->SetAlternateProtocol(
8204      HostPortPair::FromURL(request.url),
8205      666 /* port is ignored by MockConnect anyway */,
8206      AlternateProtocolFromNextProto(GetParam()));
8207
8208  scoped_ptr<HttpTransaction> trans(
8209      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8210  TestCompletionCallback callback;
8211
8212  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8213  EXPECT_EQ(ERR_IO_PENDING, rv);
8214  EXPECT_EQ(OK, callback.WaitForResult());
8215
8216  const HttpResponseInfo* response = trans->GetResponseInfo();
8217  ASSERT_TRUE(response != NULL);
8218  ASSERT_TRUE(response->headers.get() != NULL);
8219  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8220
8221  std::string response_data;
8222  ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8223  EXPECT_EQ("hello world", response_data);
8224
8225  ASSERT_TRUE(http_server_properties->HasAlternateProtocol(
8226      HostPortPair::FromURL(request.url)));
8227  const PortAlternateProtocolPair alternate =
8228      http_server_properties->GetAlternateProtocol(
8229          HostPortPair::FromURL(request.url));
8230  EXPECT_EQ(ALTERNATE_PROTOCOL_BROKEN, alternate.protocol);
8231}
8232
8233TEST_P(HttpNetworkTransactionTest,
8234       AlternateProtocolPortRestrictedBlocked) {
8235  // Ensure that we're not allowed to redirect traffic via an alternate
8236  // protocol to an unrestricted (port >= 1024) when the original traffic was
8237  // on a restricted port (port < 1024).  Ensure that we can redirect in all
8238  // other cases.
8239  HttpStreamFactory::set_use_alternate_protocols(true);
8240
8241  HttpRequestInfo restricted_port_request;
8242  restricted_port_request.method = "GET";
8243  restricted_port_request.url = GURL("http://www.google.com:1023/");
8244  restricted_port_request.load_flags = 0;
8245
8246  MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
8247  StaticSocketDataProvider first_data;
8248  first_data.set_connect_data(mock_connect);
8249  session_deps_.socket_factory->AddSocketDataProvider(&first_data);
8250
8251  MockRead data_reads[] = {
8252    MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8253    MockRead("hello world"),
8254    MockRead(ASYNC, OK),
8255  };
8256  StaticSocketDataProvider second_data(
8257      data_reads, arraysize(data_reads), NULL, 0);
8258  session_deps_.socket_factory->AddSocketDataProvider(&second_data);
8259
8260  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8261
8262  base::WeakPtr<HttpServerProperties> http_server_properties =
8263      session->http_server_properties();
8264  const int kUnrestrictedAlternatePort = 1024;
8265  http_server_properties->SetAlternateProtocol(
8266      HostPortPair::FromURL(restricted_port_request.url),
8267      kUnrestrictedAlternatePort,
8268      AlternateProtocolFromNextProto(GetParam()));
8269
8270  scoped_ptr<HttpTransaction> trans(
8271      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8272  TestCompletionCallback callback;
8273
8274  int rv = trans->Start(
8275      &restricted_port_request,
8276      callback.callback(), BoundNetLog());
8277  EXPECT_EQ(ERR_IO_PENDING, rv);
8278  // Invalid change to unrestricted port should fail.
8279  EXPECT_EQ(ERR_CONNECTION_REFUSED, callback.WaitForResult());
8280}
8281
8282TEST_P(HttpNetworkTransactionTest,
8283       AlternateProtocolPortRestrictedPermitted) {
8284  // Ensure that we're allowed to redirect traffic via an alternate
8285  // protocol to an unrestricted (port >= 1024) when the original traffic was
8286  // on a restricted port (port < 1024) if we set
8287  // enable_user_alternate_protocol_ports.
8288
8289  HttpStreamFactory::set_use_alternate_protocols(true);
8290  session_deps_.enable_user_alternate_protocol_ports = true;
8291
8292  HttpRequestInfo restricted_port_request;
8293  restricted_port_request.method = "GET";
8294  restricted_port_request.url = GURL("http://www.google.com:1023/");
8295  restricted_port_request.load_flags = 0;
8296
8297  MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
8298  StaticSocketDataProvider first_data;
8299  first_data.set_connect_data(mock_connect);
8300  session_deps_.socket_factory->AddSocketDataProvider(&first_data);
8301
8302  MockRead data_reads[] = {
8303    MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8304    MockRead("hello world"),
8305    MockRead(ASYNC, OK),
8306  };
8307  StaticSocketDataProvider second_data(
8308      data_reads, arraysize(data_reads), NULL, 0);
8309  session_deps_.socket_factory->AddSocketDataProvider(&second_data);
8310
8311  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8312
8313  base::WeakPtr<HttpServerProperties> http_server_properties =
8314      session->http_server_properties();
8315  const int kUnrestrictedAlternatePort = 1024;
8316  http_server_properties->SetAlternateProtocol(
8317      HostPortPair::FromURL(restricted_port_request.url),
8318      kUnrestrictedAlternatePort,
8319      AlternateProtocolFromNextProto(GetParam()));
8320
8321  scoped_ptr<HttpTransaction> trans(
8322      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8323  TestCompletionCallback callback;
8324
8325  EXPECT_EQ(ERR_IO_PENDING, trans->Start(
8326      &restricted_port_request,
8327      callback.callback(), BoundNetLog()));
8328  // Change to unrestricted port should succeed.
8329  EXPECT_EQ(OK, callback.WaitForResult());
8330}
8331
8332TEST_P(HttpNetworkTransactionTest,
8333       AlternateProtocolPortRestrictedAllowed) {
8334  // Ensure that we're not allowed to redirect traffic via an alternate
8335  // protocol to an unrestricted (port >= 1024) when the original traffic was
8336  // on a restricted port (port < 1024).  Ensure that we can redirect in all
8337  // other cases.
8338  HttpStreamFactory::set_use_alternate_protocols(true);
8339
8340  HttpRequestInfo restricted_port_request;
8341  restricted_port_request.method = "GET";
8342  restricted_port_request.url = GURL("http://www.google.com:1023/");
8343  restricted_port_request.load_flags = 0;
8344
8345  MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
8346  StaticSocketDataProvider first_data;
8347  first_data.set_connect_data(mock_connect);
8348  session_deps_.socket_factory->AddSocketDataProvider(&first_data);
8349
8350  MockRead data_reads[] = {
8351    MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8352    MockRead("hello world"),
8353    MockRead(ASYNC, OK),
8354  };
8355  StaticSocketDataProvider second_data(
8356      data_reads, arraysize(data_reads), NULL, 0);
8357  session_deps_.socket_factory->AddSocketDataProvider(&second_data);
8358
8359  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8360
8361  base::WeakPtr<HttpServerProperties> http_server_properties =
8362      session->http_server_properties();
8363  const int kRestrictedAlternatePort = 80;
8364  http_server_properties->SetAlternateProtocol(
8365      HostPortPair::FromURL(restricted_port_request.url),
8366      kRestrictedAlternatePort,
8367      AlternateProtocolFromNextProto(GetParam()));
8368
8369  scoped_ptr<HttpTransaction> trans(
8370      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8371  TestCompletionCallback callback;
8372
8373  int rv = trans->Start(
8374      &restricted_port_request,
8375      callback.callback(), BoundNetLog());
8376  EXPECT_EQ(ERR_IO_PENDING, rv);
8377  // Valid change to restricted port should pass.
8378  EXPECT_EQ(OK, callback.WaitForResult());
8379}
8380
8381TEST_P(HttpNetworkTransactionTest,
8382       AlternateProtocolPortUnrestrictedAllowed1) {
8383  // Ensure that we're not allowed to redirect traffic via an alternate
8384  // protocol to an unrestricted (port >= 1024) when the original traffic was
8385  // on a restricted port (port < 1024).  Ensure that we can redirect in all
8386  // other cases.
8387  HttpStreamFactory::set_use_alternate_protocols(true);
8388
8389  HttpRequestInfo unrestricted_port_request;
8390  unrestricted_port_request.method = "GET";
8391  unrestricted_port_request.url = GURL("http://www.google.com:1024/");
8392  unrestricted_port_request.load_flags = 0;
8393
8394  MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
8395  StaticSocketDataProvider first_data;
8396  first_data.set_connect_data(mock_connect);
8397  session_deps_.socket_factory->AddSocketDataProvider(&first_data);
8398
8399  MockRead data_reads[] = {
8400    MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8401    MockRead("hello world"),
8402    MockRead(ASYNC, OK),
8403  };
8404  StaticSocketDataProvider second_data(
8405      data_reads, arraysize(data_reads), NULL, 0);
8406  session_deps_.socket_factory->AddSocketDataProvider(&second_data);
8407
8408  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8409
8410  base::WeakPtr<HttpServerProperties> http_server_properties =
8411      session->http_server_properties();
8412  const int kRestrictedAlternatePort = 80;
8413  http_server_properties->SetAlternateProtocol(
8414      HostPortPair::FromURL(unrestricted_port_request.url),
8415      kRestrictedAlternatePort,
8416      AlternateProtocolFromNextProto(GetParam()));
8417
8418  scoped_ptr<HttpTransaction> trans(
8419      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8420  TestCompletionCallback callback;
8421
8422  int rv = trans->Start(
8423      &unrestricted_port_request, callback.callback(), BoundNetLog());
8424  EXPECT_EQ(ERR_IO_PENDING, rv);
8425  // Valid change to restricted port should pass.
8426  EXPECT_EQ(OK, callback.WaitForResult());
8427}
8428
8429TEST_P(HttpNetworkTransactionTest,
8430       AlternateProtocolPortUnrestrictedAllowed2) {
8431  // Ensure that we're not allowed to redirect traffic via an alternate
8432  // protocol to an unrestricted (port >= 1024) when the original traffic was
8433  // on a restricted port (port < 1024).  Ensure that we can redirect in all
8434  // other cases.
8435  HttpStreamFactory::set_use_alternate_protocols(true);
8436
8437  HttpRequestInfo unrestricted_port_request;
8438  unrestricted_port_request.method = "GET";
8439  unrestricted_port_request.url = GURL("http://www.google.com:1024/");
8440  unrestricted_port_request.load_flags = 0;
8441
8442  MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
8443  StaticSocketDataProvider first_data;
8444  first_data.set_connect_data(mock_connect);
8445  session_deps_.socket_factory->AddSocketDataProvider(&first_data);
8446
8447  MockRead data_reads[] = {
8448    MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8449    MockRead("hello world"),
8450    MockRead(ASYNC, OK),
8451  };
8452  StaticSocketDataProvider second_data(
8453      data_reads, arraysize(data_reads), NULL, 0);
8454  session_deps_.socket_factory->AddSocketDataProvider(&second_data);
8455
8456  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8457
8458  base::WeakPtr<HttpServerProperties> http_server_properties =
8459      session->http_server_properties();
8460  const int kUnrestrictedAlternatePort = 1024;
8461  http_server_properties->SetAlternateProtocol(
8462      HostPortPair::FromURL(unrestricted_port_request.url),
8463      kUnrestrictedAlternatePort,
8464      AlternateProtocolFromNextProto(GetParam()));
8465
8466  scoped_ptr<HttpTransaction> trans(
8467      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8468  TestCompletionCallback callback;
8469
8470  int rv = trans->Start(
8471      &unrestricted_port_request, callback.callback(), BoundNetLog());
8472  EXPECT_EQ(ERR_IO_PENDING, rv);
8473  // Valid change to an unrestricted port should pass.
8474  EXPECT_EQ(OK, callback.WaitForResult());
8475}
8476
8477TEST_P(HttpNetworkTransactionTest,
8478       AlternateProtocolUnsafeBlocked) {
8479  // Ensure that we're not allowed to redirect traffic via an alternate
8480  // protocol to an unsafe port, and that we resume the second
8481  // HttpStreamFactoryImpl::Job once the alternate protocol request fails.
8482  HttpStreamFactory::set_use_alternate_protocols(true);
8483
8484  HttpRequestInfo request;
8485  request.method = "GET";
8486  request.url = GURL("http://www.google.com/");
8487  request.load_flags = 0;
8488
8489  // The alternate protocol request will error out before we attempt to connect,
8490  // so only the standard HTTP request will try to connect.
8491  MockRead data_reads[] = {
8492    MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8493    MockRead("hello world"),
8494    MockRead(ASYNC, OK),
8495  };
8496  StaticSocketDataProvider data(
8497      data_reads, arraysize(data_reads), NULL, 0);
8498  session_deps_.socket_factory->AddSocketDataProvider(&data);
8499
8500  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8501
8502  base::WeakPtr<HttpServerProperties> http_server_properties =
8503      session->http_server_properties();
8504  const int kUnsafePort = 7;
8505  http_server_properties->SetAlternateProtocol(
8506      HostPortPair::FromURL(request.url),
8507      kUnsafePort,
8508      AlternateProtocolFromNextProto(GetParam()));
8509
8510  scoped_ptr<HttpTransaction> trans(
8511      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8512  TestCompletionCallback callback;
8513
8514  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8515  EXPECT_EQ(ERR_IO_PENDING, rv);
8516  // The HTTP request should succeed.
8517  EXPECT_EQ(OK, callback.WaitForResult());
8518
8519  // Disable alternate protocol before the asserts.
8520  HttpStreamFactory::set_use_alternate_protocols(false);
8521
8522  const HttpResponseInfo* response = trans->GetResponseInfo();
8523  ASSERT_TRUE(response != NULL);
8524  ASSERT_TRUE(response->headers.get() != NULL);
8525  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8526
8527  std::string response_data;
8528  ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8529  EXPECT_EQ("hello world", response_data);
8530}
8531
8532TEST_P(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) {
8533  HttpStreamFactory::set_use_alternate_protocols(true);
8534  HttpStreamFactory::SetNextProtos(SpdyNextProtos());
8535
8536  HttpRequestInfo request;
8537  request.method = "GET";
8538  request.url = GURL("http://www.google.com/");
8539  request.load_flags = 0;
8540
8541  std::string alternate_protocol_http_header =
8542      GetAlternateProtocolHttpHeader();
8543
8544  MockRead data_reads[] = {
8545    MockRead("HTTP/1.1 200 OK\r\n"),
8546    MockRead(alternate_protocol_http_header.c_str()),
8547    MockRead("hello world"),
8548    MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
8549    MockRead(ASYNC, OK)
8550  };
8551
8552  StaticSocketDataProvider first_transaction(
8553      data_reads, arraysize(data_reads), NULL, 0);
8554  session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
8555
8556  SSLSocketDataProvider ssl(ASYNC, OK);
8557  ssl.SetNextProto(GetParam());
8558  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
8559
8560  scoped_ptr<SpdyFrame> req(
8561      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
8562  MockWrite spdy_writes[] = { CreateMockWrite(*req) };
8563
8564  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
8565  scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
8566  MockRead spdy_reads[] = {
8567    CreateMockRead(*resp),
8568    CreateMockRead(*data),
8569    MockRead(ASYNC, 0, 0),
8570  };
8571
8572  DelayedSocketData spdy_data(
8573      1,  // wait for one write to finish before reading.
8574      spdy_reads, arraysize(spdy_reads),
8575      spdy_writes, arraysize(spdy_writes));
8576  session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
8577
8578  MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
8579  StaticSocketDataProvider hanging_non_alternate_protocol_socket(
8580      NULL, 0, NULL, 0);
8581  hanging_non_alternate_protocol_socket.set_connect_data(
8582      never_finishing_connect);
8583  session_deps_.socket_factory->AddSocketDataProvider(
8584      &hanging_non_alternate_protocol_socket);
8585
8586  TestCompletionCallback callback;
8587
8588  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8589  scoped_ptr<HttpTransaction> trans(
8590      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8591
8592  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8593  EXPECT_EQ(ERR_IO_PENDING, rv);
8594  EXPECT_EQ(OK, callback.WaitForResult());
8595
8596  const HttpResponseInfo* response = trans->GetResponseInfo();
8597  ASSERT_TRUE(response != NULL);
8598  ASSERT_TRUE(response->headers.get() != NULL);
8599  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8600
8601  std::string response_data;
8602  ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8603  EXPECT_EQ("hello world", response_data);
8604
8605  trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8606
8607  rv = trans->Start(&request, callback.callback(), BoundNetLog());
8608  EXPECT_EQ(ERR_IO_PENDING, rv);
8609  EXPECT_EQ(OK, callback.WaitForResult());
8610
8611  response = trans->GetResponseInfo();
8612  ASSERT_TRUE(response != NULL);
8613  ASSERT_TRUE(response->headers.get() != NULL);
8614  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8615  EXPECT_TRUE(response->was_fetched_via_spdy);
8616  EXPECT_TRUE(response->was_npn_negotiated);
8617
8618  ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8619  EXPECT_EQ("hello!", response_data);
8620}
8621
8622TEST_P(HttpNetworkTransactionTest, AlternateProtocolWithSpdyLateBinding) {
8623  HttpStreamFactory::set_use_alternate_protocols(true);
8624  HttpStreamFactory::SetNextProtos(SpdyNextProtos());
8625
8626  HttpRequestInfo request;
8627  request.method = "GET";
8628  request.url = GURL("http://www.google.com/");
8629  request.load_flags = 0;
8630
8631  std::string alternate_protocol_http_header =
8632      GetAlternateProtocolHttpHeader();
8633
8634  MockRead data_reads[] = {
8635    MockRead("HTTP/1.1 200 OK\r\n"),
8636    MockRead(alternate_protocol_http_header.c_str()),
8637    MockRead("hello world"),
8638    MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
8639    MockRead(ASYNC, OK),
8640  };
8641
8642  StaticSocketDataProvider first_transaction(
8643      data_reads, arraysize(data_reads), NULL, 0);
8644  // Socket 1 is the HTTP transaction with the Alternate-Protocol header.
8645  session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
8646
8647  MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
8648  StaticSocketDataProvider hanging_socket(
8649      NULL, 0, NULL, 0);
8650  hanging_socket.set_connect_data(never_finishing_connect);
8651  // Socket 2 and 3 are the hanging Alternate-Protocol and
8652  // non-Alternate-Protocol jobs from the 2nd transaction.
8653  session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket);
8654  session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket);
8655
8656  SSLSocketDataProvider ssl(ASYNC, OK);
8657  ssl.SetNextProto(GetParam());
8658  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
8659
8660  scoped_ptr<SpdyFrame> req1(
8661      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
8662  scoped_ptr<SpdyFrame> req2(
8663      spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
8664  MockWrite spdy_writes[] = {
8665    CreateMockWrite(*req1),
8666    CreateMockWrite(*req2),
8667  };
8668  scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
8669  scoped_ptr<SpdyFrame> data1(spdy_util_.ConstructSpdyBodyFrame(1, true));
8670  scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
8671  scoped_ptr<SpdyFrame> data2(spdy_util_.ConstructSpdyBodyFrame(3, true));
8672  MockRead spdy_reads[] = {
8673    CreateMockRead(*resp1),
8674    CreateMockRead(*data1),
8675    CreateMockRead(*resp2),
8676    CreateMockRead(*data2),
8677    MockRead(ASYNC, 0, 0),
8678  };
8679
8680  DelayedSocketData spdy_data(
8681      2,  // wait for writes to finish before reading.
8682      spdy_reads, arraysize(spdy_reads),
8683      spdy_writes, arraysize(spdy_writes));
8684  // Socket 4 is the successful Alternate-Protocol for transaction 3.
8685  session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
8686
8687  // Socket 5 is the unsuccessful non-Alternate-Protocol for transaction 3.
8688  session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket);
8689
8690  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8691  TestCompletionCallback callback1;
8692  HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
8693
8694  int rv = trans1.Start(&request, callback1.callback(), BoundNetLog());
8695  EXPECT_EQ(ERR_IO_PENDING, rv);
8696  EXPECT_EQ(OK, callback1.WaitForResult());
8697
8698  const HttpResponseInfo* response = trans1.GetResponseInfo();
8699  ASSERT_TRUE(response != NULL);
8700  ASSERT_TRUE(response->headers.get() != NULL);
8701  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8702
8703  std::string response_data;
8704  ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
8705  EXPECT_EQ("hello world", response_data);
8706
8707  TestCompletionCallback callback2;
8708  HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
8709  rv = trans2.Start(&request, callback2.callback(), BoundNetLog());
8710  EXPECT_EQ(ERR_IO_PENDING, rv);
8711
8712  TestCompletionCallback callback3;
8713  HttpNetworkTransaction trans3(DEFAULT_PRIORITY, session.get());
8714  rv = trans3.Start(&request, callback3.callback(), BoundNetLog());
8715  EXPECT_EQ(ERR_IO_PENDING, rv);
8716
8717  EXPECT_EQ(OK, callback2.WaitForResult());
8718  EXPECT_EQ(OK, callback3.WaitForResult());
8719
8720  response = trans2.GetResponseInfo();
8721  ASSERT_TRUE(response != NULL);
8722  ASSERT_TRUE(response->headers.get() != NULL);
8723  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8724  EXPECT_TRUE(response->was_fetched_via_spdy);
8725  EXPECT_TRUE(response->was_npn_negotiated);
8726  ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
8727  EXPECT_EQ("hello!", response_data);
8728
8729  response = trans3.GetResponseInfo();
8730  ASSERT_TRUE(response != NULL);
8731  ASSERT_TRUE(response->headers.get() != NULL);
8732  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8733  EXPECT_TRUE(response->was_fetched_via_spdy);
8734  EXPECT_TRUE(response->was_npn_negotiated);
8735  ASSERT_EQ(OK, ReadTransaction(&trans3, &response_data));
8736  EXPECT_EQ("hello!", response_data);
8737}
8738
8739TEST_P(HttpNetworkTransactionTest, StallAlternateProtocolForNpnSpdy) {
8740  HttpStreamFactory::set_use_alternate_protocols(true);
8741  HttpStreamFactory::SetNextProtos(SpdyNextProtos());
8742
8743  HttpRequestInfo request;
8744  request.method = "GET";
8745  request.url = GURL("http://www.google.com/");
8746  request.load_flags = 0;
8747
8748  std::string alternate_protocol_http_header =
8749      GetAlternateProtocolHttpHeader();
8750
8751  MockRead data_reads[] = {
8752    MockRead("HTTP/1.1 200 OK\r\n"),
8753    MockRead(alternate_protocol_http_header.c_str()),
8754    MockRead("hello world"),
8755    MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
8756    MockRead(ASYNC, OK),
8757  };
8758
8759  StaticSocketDataProvider first_transaction(
8760      data_reads, arraysize(data_reads), NULL, 0);
8761  session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
8762
8763  SSLSocketDataProvider ssl(ASYNC, OK);
8764  ssl.SetNextProto(GetParam());
8765  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
8766
8767  MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
8768  StaticSocketDataProvider hanging_alternate_protocol_socket(
8769      NULL, 0, NULL, 0);
8770  hanging_alternate_protocol_socket.set_connect_data(
8771      never_finishing_connect);
8772  session_deps_.socket_factory->AddSocketDataProvider(
8773      &hanging_alternate_protocol_socket);
8774
8775  // 2nd request is just a copy of the first one, over HTTP again.
8776  session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
8777
8778  TestCompletionCallback callback;
8779
8780  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8781  scoped_ptr<HttpTransaction> trans(
8782      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8783
8784  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8785  EXPECT_EQ(ERR_IO_PENDING, rv);
8786  EXPECT_EQ(OK, callback.WaitForResult());
8787
8788  const HttpResponseInfo* response = trans->GetResponseInfo();
8789  ASSERT_TRUE(response != NULL);
8790  ASSERT_TRUE(response->headers.get() != NULL);
8791  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8792
8793  std::string response_data;
8794  ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8795  EXPECT_EQ("hello world", response_data);
8796
8797  trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8798
8799  rv = trans->Start(&request, callback.callback(), BoundNetLog());
8800  EXPECT_EQ(ERR_IO_PENDING, rv);
8801  EXPECT_EQ(OK, callback.WaitForResult());
8802
8803  response = trans->GetResponseInfo();
8804  ASSERT_TRUE(response != NULL);
8805  ASSERT_TRUE(response->headers.get() != NULL);
8806  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8807  EXPECT_FALSE(response->was_fetched_via_spdy);
8808  EXPECT_FALSE(response->was_npn_negotiated);
8809
8810  ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8811  EXPECT_EQ("hello world", response_data);
8812}
8813
8814class CapturingProxyResolver : public ProxyResolver {
8815 public:
8816  CapturingProxyResolver() : ProxyResolver(false /* expects_pac_bytes */) {}
8817  virtual ~CapturingProxyResolver() {}
8818
8819  virtual int GetProxyForURL(const GURL& url,
8820                             ProxyInfo* results,
8821                             const CompletionCallback& callback,
8822                             RequestHandle* request,
8823                             const BoundNetLog& net_log) OVERRIDE {
8824    ProxyServer proxy_server(ProxyServer::SCHEME_HTTP,
8825                             HostPortPair("myproxy", 80));
8826    results->UseProxyServer(proxy_server);
8827    resolved_.push_back(url);
8828    return OK;
8829  }
8830
8831  virtual void CancelRequest(RequestHandle request) OVERRIDE {
8832    NOTREACHED();
8833  }
8834
8835  virtual LoadState GetLoadState(RequestHandle request) const OVERRIDE {
8836    NOTREACHED();
8837    return LOAD_STATE_IDLE;
8838  }
8839
8840  virtual void CancelSetPacScript() OVERRIDE {
8841    NOTREACHED();
8842  }
8843
8844  virtual int SetPacScript(const scoped_refptr<ProxyResolverScriptData>&,
8845                           const CompletionCallback& /*callback*/) OVERRIDE {
8846    return OK;
8847  }
8848
8849  const std::vector<GURL>& resolved() const { return resolved_; }
8850
8851 private:
8852  std::vector<GURL> resolved_;
8853
8854  DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver);
8855};
8856
8857TEST_P(HttpNetworkTransactionTest,
8858       UseAlternateProtocolForTunneledNpnSpdy) {
8859  HttpStreamFactory::set_use_alternate_protocols(true);
8860  HttpStreamFactory::SetNextProtos(SpdyNextProtos());
8861
8862  ProxyConfig proxy_config;
8863  proxy_config.set_auto_detect(true);
8864  proxy_config.set_pac_url(GURL("http://fooproxyurl"));
8865
8866  CapturingProxyResolver* capturing_proxy_resolver =
8867      new CapturingProxyResolver();
8868  session_deps_.proxy_service.reset(new ProxyService(
8869      new ProxyConfigServiceFixed(proxy_config), capturing_proxy_resolver,
8870      NULL));
8871  CapturingNetLog net_log;
8872  session_deps_.net_log = &net_log;
8873
8874  HttpRequestInfo request;
8875  request.method = "GET";
8876  request.url = GURL("http://www.google.com/");
8877  request.load_flags = 0;
8878
8879  std::string alternate_protocol_http_header =
8880      GetAlternateProtocolHttpHeader();
8881
8882  MockRead data_reads[] = {
8883    MockRead("HTTP/1.1 200 OK\r\n"),
8884    MockRead(alternate_protocol_http_header.c_str()),
8885    MockRead("hello world"),
8886    MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
8887    MockRead(ASYNC, OK),
8888  };
8889
8890  StaticSocketDataProvider first_transaction(
8891      data_reads, arraysize(data_reads), NULL, 0);
8892  session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
8893
8894  SSLSocketDataProvider ssl(ASYNC, OK);
8895  ssl.SetNextProto(GetParam());
8896  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
8897
8898  scoped_ptr<SpdyFrame> req(
8899      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
8900  MockWrite spdy_writes[] = {
8901    MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
8902              "Host: www.google.com\r\n"
8903              "Proxy-Connection: keep-alive\r\n\r\n"),  // 0
8904    CreateMockWrite(*req),                              // 3
8905  };
8906
8907  const char kCONNECTResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
8908
8909  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
8910  scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
8911  MockRead spdy_reads[] = {
8912    MockRead(ASYNC, kCONNECTResponse, arraysize(kCONNECTResponse) - 1, 1),  // 1
8913    CreateMockRead(*resp.get(), 4),  // 2, 4
8914    CreateMockRead(*data.get(), 4),  // 5
8915    MockRead(ASYNC, 0, 0, 4),  // 6
8916  };
8917
8918  OrderedSocketData spdy_data(
8919      spdy_reads, arraysize(spdy_reads),
8920      spdy_writes, arraysize(spdy_writes));
8921  session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
8922
8923  MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
8924  StaticSocketDataProvider hanging_non_alternate_protocol_socket(
8925      NULL, 0, NULL, 0);
8926  hanging_non_alternate_protocol_socket.set_connect_data(
8927      never_finishing_connect);
8928  session_deps_.socket_factory->AddSocketDataProvider(
8929      &hanging_non_alternate_protocol_socket);
8930
8931  TestCompletionCallback callback;
8932
8933  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8934  scoped_ptr<HttpTransaction> trans(
8935      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8936
8937  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8938  EXPECT_EQ(ERR_IO_PENDING, rv);
8939  EXPECT_EQ(OK, callback.WaitForResult());
8940
8941  const HttpResponseInfo* response = trans->GetResponseInfo();
8942  ASSERT_TRUE(response != NULL);
8943  ASSERT_TRUE(response->headers.get() != NULL);
8944  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8945  EXPECT_FALSE(response->was_fetched_via_spdy);
8946  EXPECT_FALSE(response->was_npn_negotiated);
8947
8948  std::string response_data;
8949  ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8950  EXPECT_EQ("hello world", response_data);
8951
8952  trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8953
8954  rv = trans->Start(&request, callback.callback(), BoundNetLog());
8955  EXPECT_EQ(ERR_IO_PENDING, rv);
8956  EXPECT_EQ(OK, callback.WaitForResult());
8957
8958  response = trans->GetResponseInfo();
8959  ASSERT_TRUE(response != NULL);
8960  ASSERT_TRUE(response->headers.get() != NULL);
8961  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8962  EXPECT_TRUE(response->was_fetched_via_spdy);
8963  EXPECT_TRUE(response->was_npn_negotiated);
8964
8965  ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8966  EXPECT_EQ("hello!", response_data);
8967  ASSERT_EQ(3u, capturing_proxy_resolver->resolved().size());
8968  EXPECT_EQ("http://www.google.com/",
8969            capturing_proxy_resolver->resolved()[0].spec());
8970  EXPECT_EQ("https://www.google.com/",
8971            capturing_proxy_resolver->resolved()[1].spec());
8972
8973  LoadTimingInfo load_timing_info;
8974  EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
8975  TestLoadTimingNotReusedWithPac(load_timing_info,
8976                                 CONNECT_TIMING_HAS_SSL_TIMES);
8977}
8978
8979TEST_P(HttpNetworkTransactionTest,
8980       UseAlternateProtocolForNpnSpdyWithExistingSpdySession) {
8981  HttpStreamFactory::set_use_alternate_protocols(true);
8982  HttpStreamFactory::SetNextProtos(SpdyNextProtos());
8983
8984  HttpRequestInfo request;
8985  request.method = "GET";
8986  request.url = GURL("http://www.google.com/");
8987  request.load_flags = 0;
8988
8989  std::string alternate_protocol_http_header =
8990      GetAlternateProtocolHttpHeader();
8991
8992  MockRead data_reads[] = {
8993    MockRead("HTTP/1.1 200 OK\r\n"),
8994    MockRead(alternate_protocol_http_header.c_str()),
8995    MockRead("hello world"),
8996    MockRead(ASYNC, OK),
8997  };
8998
8999  StaticSocketDataProvider first_transaction(
9000      data_reads, arraysize(data_reads), NULL, 0);
9001  session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
9002
9003  SSLSocketDataProvider ssl(ASYNC, OK);
9004  ssl.SetNextProto(GetParam());
9005  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9006
9007  scoped_ptr<SpdyFrame> req(
9008      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
9009  MockWrite spdy_writes[] = { CreateMockWrite(*req) };
9010
9011  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
9012  scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
9013  MockRead spdy_reads[] = {
9014    CreateMockRead(*resp),
9015    CreateMockRead(*data),
9016    MockRead(ASYNC, 0, 0),
9017  };
9018
9019  DelayedSocketData spdy_data(
9020      1,  // wait for one write to finish before reading.
9021      spdy_reads, arraysize(spdy_reads),
9022      spdy_writes, arraysize(spdy_writes));
9023  session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
9024
9025  TestCompletionCallback callback;
9026
9027  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9028
9029  scoped_ptr<HttpTransaction> trans(
9030      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9031
9032  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9033  EXPECT_EQ(ERR_IO_PENDING, rv);
9034  EXPECT_EQ(OK, callback.WaitForResult());
9035
9036  const HttpResponseInfo* response = trans->GetResponseInfo();
9037  ASSERT_TRUE(response != NULL);
9038  ASSERT_TRUE(response->headers.get() != NULL);
9039  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9040
9041  std::string response_data;
9042  ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9043  EXPECT_EQ("hello world", response_data);
9044
9045  // Set up an initial SpdySession in the pool to reuse.
9046  HostPortPair host_port_pair("www.google.com", 443);
9047  SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
9048                     kPrivacyModeDisabled);
9049  base::WeakPtr<SpdySession> spdy_session =
9050      CreateSecureSpdySession(session, key, BoundNetLog());
9051
9052  trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9053
9054  rv = trans->Start(&request, callback.callback(), BoundNetLog());
9055  EXPECT_EQ(ERR_IO_PENDING, rv);
9056  EXPECT_EQ(OK, callback.WaitForResult());
9057
9058  response = trans->GetResponseInfo();
9059  ASSERT_TRUE(response != NULL);
9060  ASSERT_TRUE(response->headers.get() != NULL);
9061  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9062  EXPECT_TRUE(response->was_fetched_via_spdy);
9063  EXPECT_TRUE(response->was_npn_negotiated);
9064
9065  ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9066  EXPECT_EQ("hello!", response_data);
9067}
9068
9069// GenerateAuthToken is a mighty big test.
9070// It tests all permutation of GenerateAuthToken behavior:
9071//   - Synchronous and Asynchronous completion.
9072//   - OK or error on completion.
9073//   - Direct connection, non-authenticating proxy, and authenticating proxy.
9074//   - HTTP or HTTPS backend (to include proxy tunneling).
9075//   - Non-authenticating and authenticating backend.
9076//
9077// In all, there are 44 reasonable permuations (for example, if there are
9078// problems generating an auth token for an authenticating proxy, we don't
9079// need to test all permutations of the backend server).
9080//
9081// The test proceeds by going over each of the configuration cases, and
9082// potentially running up to three rounds in each of the tests. The TestConfig
9083// specifies both the configuration for the test as well as the expectations
9084// for the results.
9085TEST_P(HttpNetworkTransactionTest, GenerateAuthToken) {
9086  static const char kServer[] = "http://www.example.com";
9087  static const char kSecureServer[] = "https://www.example.com";
9088  static const char kProxy[] = "myproxy:70";
9089  const int kAuthErr = ERR_INVALID_AUTH_CREDENTIALS;
9090
9091  enum AuthTiming {
9092    AUTH_NONE,
9093    AUTH_SYNC,
9094    AUTH_ASYNC,
9095  };
9096
9097  const MockWrite kGet(
9098      "GET / HTTP/1.1\r\n"
9099      "Host: www.example.com\r\n"
9100      "Connection: keep-alive\r\n\r\n");
9101  const MockWrite kGetProxy(
9102      "GET http://www.example.com/ HTTP/1.1\r\n"
9103      "Host: www.example.com\r\n"
9104      "Proxy-Connection: keep-alive\r\n\r\n");
9105  const MockWrite kGetAuth(
9106      "GET / HTTP/1.1\r\n"
9107      "Host: www.example.com\r\n"
9108      "Connection: keep-alive\r\n"
9109      "Authorization: auth_token\r\n\r\n");
9110  const MockWrite kGetProxyAuth(
9111      "GET http://www.example.com/ HTTP/1.1\r\n"
9112      "Host: www.example.com\r\n"
9113      "Proxy-Connection: keep-alive\r\n"
9114      "Proxy-Authorization: auth_token\r\n\r\n");
9115  const MockWrite kGetAuthThroughProxy(
9116      "GET http://www.example.com/ HTTP/1.1\r\n"
9117      "Host: www.example.com\r\n"
9118      "Proxy-Connection: keep-alive\r\n"
9119      "Authorization: auth_token\r\n\r\n");
9120  const MockWrite kGetAuthWithProxyAuth(
9121      "GET http://www.example.com/ HTTP/1.1\r\n"
9122      "Host: www.example.com\r\n"
9123      "Proxy-Connection: keep-alive\r\n"
9124      "Proxy-Authorization: auth_token\r\n"
9125      "Authorization: auth_token\r\n\r\n");
9126  const MockWrite kConnect(
9127      "CONNECT www.example.com:443 HTTP/1.1\r\n"
9128      "Host: www.example.com\r\n"
9129      "Proxy-Connection: keep-alive\r\n\r\n");
9130  const MockWrite kConnectProxyAuth(
9131      "CONNECT www.example.com:443 HTTP/1.1\r\n"
9132      "Host: www.example.com\r\n"
9133      "Proxy-Connection: keep-alive\r\n"
9134      "Proxy-Authorization: auth_token\r\n\r\n");
9135
9136  const MockRead kSuccess(
9137      "HTTP/1.1 200 OK\r\n"
9138      "Content-Type: text/html; charset=iso-8859-1\r\n"
9139      "Content-Length: 3\r\n\r\n"
9140      "Yes");
9141  const MockRead kFailure(
9142      "Should not be called.");
9143  const MockRead kServerChallenge(
9144      "HTTP/1.1 401 Unauthorized\r\n"
9145      "WWW-Authenticate: Mock realm=server\r\n"
9146      "Content-Type: text/html; charset=iso-8859-1\r\n"
9147      "Content-Length: 14\r\n\r\n"
9148      "Unauthorized\r\n");
9149  const MockRead kProxyChallenge(
9150      "HTTP/1.1 407 Unauthorized\r\n"
9151      "Proxy-Authenticate: Mock realm=proxy\r\n"
9152      "Proxy-Connection: close\r\n"
9153      "Content-Type: text/html; charset=iso-8859-1\r\n"
9154      "Content-Length: 14\r\n\r\n"
9155      "Unauthorized\r\n");
9156  const MockRead kProxyConnected(
9157      "HTTP/1.1 200 Connection Established\r\n\r\n");
9158
9159  // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
9160  // no constructors, but the C++ compiler on Windows warns about
9161  // unspecified data in compound literals. So, moved to using constructors,
9162  // and TestRound's created with the default constructor should not be used.
9163  struct TestRound {
9164    TestRound()
9165        : expected_rv(ERR_UNEXPECTED),
9166          extra_write(NULL),
9167          extra_read(NULL) {
9168    }
9169    TestRound(const MockWrite& write_arg, const MockRead& read_arg,
9170              int expected_rv_arg)
9171        : write(write_arg),
9172          read(read_arg),
9173          expected_rv(expected_rv_arg),
9174          extra_write(NULL),
9175          extra_read(NULL) {
9176    }
9177    TestRound(const MockWrite& write_arg, const MockRead& read_arg,
9178              int expected_rv_arg, const MockWrite* extra_write_arg,
9179              const MockRead* extra_read_arg)
9180        : write(write_arg),
9181          read(read_arg),
9182          expected_rv(expected_rv_arg),
9183          extra_write(extra_write_arg),
9184          extra_read(extra_read_arg) {
9185    }
9186    MockWrite write;
9187    MockRead read;
9188    int expected_rv;
9189    const MockWrite* extra_write;
9190    const MockRead* extra_read;
9191  };
9192
9193  static const int kNoSSL = 500;
9194
9195  struct TestConfig {
9196    const char* proxy_url;
9197    AuthTiming proxy_auth_timing;
9198    int proxy_auth_rv;
9199    const char* server_url;
9200    AuthTiming server_auth_timing;
9201    int server_auth_rv;
9202    int num_auth_rounds;
9203    int first_ssl_round;
9204    TestRound rounds[3];
9205  } test_configs[] = {
9206    // Non-authenticating HTTP server with a direct connection.
9207    { NULL, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
9208      { TestRound(kGet, kSuccess, OK)}},
9209    // Authenticating HTTP server with a direct connection.
9210    { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
9211      { TestRound(kGet, kServerChallenge, OK),
9212        TestRound(kGetAuth, kSuccess, OK)}},
9213    { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
9214      { TestRound(kGet, kServerChallenge, OK),
9215        TestRound(kGetAuth, kFailure, kAuthErr)}},
9216    { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
9217      { TestRound(kGet, kServerChallenge, OK),
9218        TestRound(kGetAuth, kSuccess, OK)}},
9219    { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
9220      { TestRound(kGet, kServerChallenge, OK),
9221        TestRound(kGetAuth, kFailure, kAuthErr)}},
9222    // Non-authenticating HTTP server through a non-authenticating proxy.
9223    { kProxy, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
9224      { TestRound(kGetProxy, kSuccess, OK)}},
9225    // Authenticating HTTP server through a non-authenticating proxy.
9226    { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
9227      { TestRound(kGetProxy, kServerChallenge, OK),
9228        TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
9229    { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
9230      { TestRound(kGetProxy, kServerChallenge, OK),
9231        TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
9232    { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
9233      { TestRound(kGetProxy, kServerChallenge, OK),
9234        TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
9235    { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
9236      { TestRound(kGetProxy, kServerChallenge, OK),
9237        TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
9238    // Non-authenticating HTTP server through an authenticating proxy.
9239    { kProxy, AUTH_SYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
9240      { TestRound(kGetProxy, kProxyChallenge, OK),
9241        TestRound(kGetProxyAuth, kSuccess, OK)}},
9242    { kProxy, AUTH_SYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
9243      { TestRound(kGetProxy, kProxyChallenge, OK),
9244        TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
9245    { kProxy, AUTH_ASYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
9246      { TestRound(kGetProxy, kProxyChallenge, OK),
9247        TestRound(kGetProxyAuth, kSuccess, OK)}},
9248    { kProxy, AUTH_ASYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
9249      { TestRound(kGetProxy, kProxyChallenge, OK),
9250        TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
9251    // Authenticating HTTP server through an authenticating proxy.
9252    { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
9253      { TestRound(kGetProxy, kProxyChallenge, OK),
9254        TestRound(kGetProxyAuth, kServerChallenge, OK),
9255        TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
9256    { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
9257      { TestRound(kGetProxy, kProxyChallenge, OK),
9258        TestRound(kGetProxyAuth, kServerChallenge, OK),
9259        TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
9260    { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
9261      { TestRound(kGetProxy, kProxyChallenge, OK),
9262        TestRound(kGetProxyAuth, kServerChallenge, OK),
9263        TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
9264    { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
9265      { TestRound(kGetProxy, kProxyChallenge, OK),
9266        TestRound(kGetProxyAuth, kServerChallenge, OK),
9267        TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
9268    { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
9269      { TestRound(kGetProxy, kProxyChallenge, OK),
9270        TestRound(kGetProxyAuth, kServerChallenge, OK),
9271        TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
9272    { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
9273      { TestRound(kGetProxy, kProxyChallenge, OK),
9274        TestRound(kGetProxyAuth, kServerChallenge, OK),
9275        TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
9276    { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
9277      { TestRound(kGetProxy, kProxyChallenge, OK),
9278        TestRound(kGetProxyAuth, kServerChallenge, OK),
9279        TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
9280    { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
9281      { TestRound(kGetProxy, kProxyChallenge, OK),
9282        TestRound(kGetProxyAuth, kServerChallenge, OK),
9283        TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
9284    // Non-authenticating HTTPS server with a direct connection.
9285    { NULL, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
9286      { TestRound(kGet, kSuccess, OK)}},
9287    // Authenticating HTTPS server with a direct connection.
9288    { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
9289      { TestRound(kGet, kServerChallenge, OK),
9290        TestRound(kGetAuth, kSuccess, OK)}},
9291    { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
9292      { TestRound(kGet, kServerChallenge, OK),
9293        TestRound(kGetAuth, kFailure, kAuthErr)}},
9294    { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
9295      { TestRound(kGet, kServerChallenge, OK),
9296        TestRound(kGetAuth, kSuccess, OK)}},
9297    { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
9298      { TestRound(kGet, kServerChallenge, OK),
9299        TestRound(kGetAuth, kFailure, kAuthErr)}},
9300    // Non-authenticating HTTPS server with a non-authenticating proxy.
9301    { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
9302      { TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
9303    // Authenticating HTTPS server through a non-authenticating proxy.
9304    { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
9305      { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
9306        TestRound(kGetAuth, kSuccess, OK)}},
9307    { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
9308      { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
9309        TestRound(kGetAuth, kFailure, kAuthErr)}},
9310    { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
9311      { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
9312        TestRound(kGetAuth, kSuccess, OK)}},
9313    { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
9314      { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
9315        TestRound(kGetAuth, kFailure, kAuthErr)}},
9316    // Non-Authenticating HTTPS server through an authenticating proxy.
9317    { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
9318      { TestRound(kConnect, kProxyChallenge, OK),
9319        TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
9320    { kProxy, AUTH_SYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
9321      { TestRound(kConnect, kProxyChallenge, OK),
9322        TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
9323    { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
9324      { TestRound(kConnect, kProxyChallenge, OK),
9325        TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
9326    { kProxy, AUTH_ASYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
9327      { TestRound(kConnect, kProxyChallenge, OK),
9328        TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
9329    // Authenticating HTTPS server through an authenticating proxy.
9330    { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
9331      { TestRound(kConnect, kProxyChallenge, OK),
9332        TestRound(kConnectProxyAuth, kProxyConnected, OK,
9333                  &kGet, &kServerChallenge),
9334        TestRound(kGetAuth, kSuccess, OK)}},
9335    { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
9336      { TestRound(kConnect, kProxyChallenge, OK),
9337        TestRound(kConnectProxyAuth, kProxyConnected, OK,
9338                  &kGet, &kServerChallenge),
9339        TestRound(kGetAuth, kFailure, kAuthErr)}},
9340    { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
9341      { TestRound(kConnect, kProxyChallenge, OK),
9342        TestRound(kConnectProxyAuth, kProxyConnected, OK,
9343                  &kGet, &kServerChallenge),
9344        TestRound(kGetAuth, kSuccess, OK)}},
9345    { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
9346      { TestRound(kConnect, kProxyChallenge, OK),
9347        TestRound(kConnectProxyAuth, kProxyConnected, OK,
9348                  &kGet, &kServerChallenge),
9349        TestRound(kGetAuth, kFailure, kAuthErr)}},
9350    { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
9351      { TestRound(kConnect, kProxyChallenge, OK),
9352        TestRound(kConnectProxyAuth, kProxyConnected, OK,
9353                  &kGet, &kServerChallenge),
9354        TestRound(kGetAuth, kSuccess, OK)}},
9355    { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
9356      { TestRound(kConnect, kProxyChallenge, OK),
9357        TestRound(kConnectProxyAuth, kProxyConnected, OK,
9358                  &kGet, &kServerChallenge),
9359        TestRound(kGetAuth, kFailure, kAuthErr)}},
9360    { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
9361      { TestRound(kConnect, kProxyChallenge, OK),
9362        TestRound(kConnectProxyAuth, kProxyConnected, OK,
9363                  &kGet, &kServerChallenge),
9364        TestRound(kGetAuth, kSuccess, OK)}},
9365    { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
9366      { TestRound(kConnect, kProxyChallenge, OK),
9367        TestRound(kConnectProxyAuth, kProxyConnected, OK,
9368                  &kGet, &kServerChallenge),
9369        TestRound(kGetAuth, kFailure, kAuthErr)}},
9370  };
9371
9372  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_configs); ++i) {
9373    HttpAuthHandlerMock::Factory* auth_factory(
9374        new HttpAuthHandlerMock::Factory());
9375    session_deps_.http_auth_handler_factory.reset(auth_factory);
9376    const TestConfig& test_config = test_configs[i];
9377
9378    // Set up authentication handlers as necessary.
9379    if (test_config.proxy_auth_timing != AUTH_NONE) {
9380      for (int n = 0; n < 2; n++) {
9381        HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
9382        std::string auth_challenge = "Mock realm=proxy";
9383        GURL origin(test_config.proxy_url);
9384        HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
9385                                               auth_challenge.end());
9386        auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_PROXY,
9387                                        origin, BoundNetLog());
9388        auth_handler->SetGenerateExpectation(
9389            test_config.proxy_auth_timing == AUTH_ASYNC,
9390            test_config.proxy_auth_rv);
9391        auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_PROXY);
9392      }
9393    }
9394    if (test_config.server_auth_timing != AUTH_NONE) {
9395      HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
9396      std::string auth_challenge = "Mock realm=server";
9397      GURL origin(test_config.server_url);
9398      HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
9399                                             auth_challenge.end());
9400      auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
9401                                      origin, BoundNetLog());
9402      auth_handler->SetGenerateExpectation(
9403          test_config.server_auth_timing == AUTH_ASYNC,
9404          test_config.server_auth_rv);
9405      auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
9406    }
9407    if (test_config.proxy_url) {
9408      session_deps_.proxy_service.reset(
9409          ProxyService::CreateFixed(test_config.proxy_url));
9410    } else {
9411      session_deps_.proxy_service.reset(ProxyService::CreateDirect());
9412    }
9413
9414    HttpRequestInfo request;
9415    request.method = "GET";
9416    request.url = GURL(test_config.server_url);
9417    request.load_flags = 0;
9418
9419    scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9420    HttpNetworkTransaction trans(DEFAULT_PRIORITY, session);
9421
9422    for (int round = 0; round < test_config.num_auth_rounds; ++round) {
9423      const TestRound& read_write_round = test_config.rounds[round];
9424
9425      // Set up expected reads and writes.
9426      MockRead reads[2];
9427      reads[0] = read_write_round.read;
9428      size_t length_reads = 1;
9429      if (read_write_round.extra_read) {
9430        reads[1] = *read_write_round.extra_read;
9431        length_reads = 2;
9432      }
9433
9434      MockWrite writes[2];
9435      writes[0] = read_write_round.write;
9436      size_t length_writes = 1;
9437      if (read_write_round.extra_write) {
9438        writes[1] = *read_write_round.extra_write;
9439        length_writes = 2;
9440      }
9441      StaticSocketDataProvider data_provider(
9442          reads, length_reads, writes, length_writes);
9443      session_deps_.socket_factory->AddSocketDataProvider(&data_provider);
9444
9445      // Add an SSL sequence if necessary.
9446      SSLSocketDataProvider ssl_socket_data_provider(SYNCHRONOUS, OK);
9447      if (round >= test_config.first_ssl_round)
9448        session_deps_.socket_factory->AddSSLSocketDataProvider(
9449            &ssl_socket_data_provider);
9450
9451      // Start or restart the transaction.
9452      TestCompletionCallback callback;
9453      int rv;
9454      if (round == 0) {
9455        rv = trans.Start(&request, callback.callback(), BoundNetLog());
9456      } else {
9457        rv = trans.RestartWithAuth(
9458            AuthCredentials(kFoo, kBar), callback.callback());
9459      }
9460      if (rv == ERR_IO_PENDING)
9461        rv = callback.WaitForResult();
9462
9463      // Compare results with expected data.
9464      EXPECT_EQ(read_write_round.expected_rv, rv);
9465      const HttpResponseInfo* response = trans.GetResponseInfo();
9466      if (read_write_round.expected_rv == OK) {
9467        ASSERT_TRUE(response != NULL);
9468      } else {
9469        EXPECT_TRUE(response == NULL);
9470        EXPECT_EQ(round + 1, test_config.num_auth_rounds);
9471        continue;
9472      }
9473      if (round + 1 < test_config.num_auth_rounds) {
9474        EXPECT_FALSE(response->auth_challenge.get() == NULL);
9475      } else {
9476        EXPECT_TRUE(response->auth_challenge.get() == NULL);
9477      }
9478    }
9479  }
9480}
9481
9482TEST_P(HttpNetworkTransactionTest, MultiRoundAuth) {
9483  // Do multi-round authentication and make sure it works correctly.
9484  HttpAuthHandlerMock::Factory* auth_factory(
9485      new HttpAuthHandlerMock::Factory());
9486  session_deps_.http_auth_handler_factory.reset(auth_factory);
9487  session_deps_.proxy_service.reset(ProxyService::CreateDirect());
9488  session_deps_.host_resolver->rules()->AddRule("www.example.com", "10.0.0.1");
9489  session_deps_.host_resolver->set_synchronous_mode(true);
9490
9491  HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
9492  auth_handler->set_connection_based(true);
9493  std::string auth_challenge = "Mock realm=server";
9494  GURL origin("http://www.example.com");
9495  HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
9496                                         auth_challenge.end());
9497  auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
9498                                  origin, BoundNetLog());
9499  auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
9500
9501  int rv = OK;
9502  const HttpResponseInfo* response = NULL;
9503  HttpRequestInfo request;
9504  request.method = "GET";
9505  request.url = origin;
9506  request.load_flags = 0;
9507
9508  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9509
9510  // Use a TCP Socket Pool with only one connection per group. This is used
9511  // to validate that the TCP socket is not released to the pool between
9512  // each round of multi-round authentication.
9513  HttpNetworkSessionPeer session_peer(session);
9514  ClientSocketPoolHistograms transport_pool_histograms("SmallTCP");
9515  TransportClientSocketPool* transport_pool = new TransportClientSocketPool(
9516      50,  // Max sockets for pool
9517      1,   // Max sockets per group
9518      &transport_pool_histograms,
9519      session_deps_.host_resolver.get(),
9520      session_deps_.socket_factory.get(),
9521      session_deps_.net_log);
9522  scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
9523      new MockClientSocketPoolManager);
9524  mock_pool_manager->SetTransportSocketPool(transport_pool);
9525  session_peer.SetClientSocketPoolManager(
9526      mock_pool_manager.PassAs<ClientSocketPoolManager>());
9527
9528  scoped_ptr<HttpTransaction> trans(
9529      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9530  TestCompletionCallback callback;
9531
9532  const MockWrite kGet(
9533      "GET / HTTP/1.1\r\n"
9534      "Host: www.example.com\r\n"
9535      "Connection: keep-alive\r\n\r\n");
9536  const MockWrite kGetAuth(
9537      "GET / HTTP/1.1\r\n"
9538      "Host: www.example.com\r\n"
9539      "Connection: keep-alive\r\n"
9540      "Authorization: auth_token\r\n\r\n");
9541
9542  const MockRead kServerChallenge(
9543      "HTTP/1.1 401 Unauthorized\r\n"
9544      "WWW-Authenticate: Mock realm=server\r\n"
9545      "Content-Type: text/html; charset=iso-8859-1\r\n"
9546      "Content-Length: 14\r\n\r\n"
9547      "Unauthorized\r\n");
9548  const MockRead kSuccess(
9549      "HTTP/1.1 200 OK\r\n"
9550      "Content-Type: text/html; charset=iso-8859-1\r\n"
9551      "Content-Length: 3\r\n\r\n"
9552      "Yes");
9553
9554  MockWrite writes[] = {
9555    // First round
9556    kGet,
9557    // Second round
9558    kGetAuth,
9559    // Third round
9560    kGetAuth,
9561    // Fourth round
9562    kGetAuth,
9563    // Competing request
9564    kGet,
9565  };
9566  MockRead reads[] = {
9567    // First round
9568    kServerChallenge,
9569    // Second round
9570    kServerChallenge,
9571    // Third round
9572    kServerChallenge,
9573    // Fourth round
9574    kSuccess,
9575    // Competing response
9576    kSuccess,
9577  };
9578  StaticSocketDataProvider data_provider(reads, arraysize(reads),
9579                                         writes, arraysize(writes));
9580  session_deps_.socket_factory->AddSocketDataProvider(&data_provider);
9581
9582  const char* const kSocketGroup = "www.example.com:80";
9583
9584  // First round of authentication.
9585  auth_handler->SetGenerateExpectation(false, OK);
9586  rv = trans->Start(&request, callback.callback(), BoundNetLog());
9587  if (rv == ERR_IO_PENDING)
9588    rv = callback.WaitForResult();
9589  EXPECT_EQ(OK, rv);
9590  response = trans->GetResponseInfo();
9591  ASSERT_TRUE(response != NULL);
9592  EXPECT_FALSE(response->auth_challenge.get() == NULL);
9593  EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
9594
9595  // In between rounds, another request comes in for the same domain.
9596  // It should not be able to grab the TCP socket that trans has already
9597  // claimed.
9598  scoped_ptr<HttpTransaction> trans_compete(
9599      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9600  TestCompletionCallback callback_compete;
9601  rv = trans_compete->Start(
9602      &request, callback_compete.callback(), BoundNetLog());
9603  EXPECT_EQ(ERR_IO_PENDING, rv);
9604  // callback_compete.WaitForResult at this point would stall forever,
9605  // since the HttpNetworkTransaction does not release the request back to
9606  // the pool until after authentication completes.
9607
9608  // Second round of authentication.
9609  auth_handler->SetGenerateExpectation(false, OK);
9610  rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
9611  if (rv == ERR_IO_PENDING)
9612    rv = callback.WaitForResult();
9613  EXPECT_EQ(OK, rv);
9614  response = trans->GetResponseInfo();
9615  ASSERT_TRUE(response != NULL);
9616  EXPECT_TRUE(response->auth_challenge.get() == NULL);
9617  EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
9618
9619  // Third round of authentication.
9620  auth_handler->SetGenerateExpectation(false, OK);
9621  rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
9622  if (rv == ERR_IO_PENDING)
9623    rv = callback.WaitForResult();
9624  EXPECT_EQ(OK, rv);
9625  response = trans->GetResponseInfo();
9626  ASSERT_TRUE(response != NULL);
9627  EXPECT_TRUE(response->auth_challenge.get() == NULL);
9628  EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
9629
9630  // Fourth round of authentication, which completes successfully.
9631  auth_handler->SetGenerateExpectation(false, OK);
9632  rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
9633  if (rv == ERR_IO_PENDING)
9634    rv = callback.WaitForResult();
9635  EXPECT_EQ(OK, rv);
9636  response = trans->GetResponseInfo();
9637  ASSERT_TRUE(response != NULL);
9638  EXPECT_TRUE(response->auth_challenge.get() == NULL);
9639  EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
9640
9641  // Read the body since the fourth round was successful. This will also
9642  // release the socket back to the pool.
9643  scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(50));
9644  rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
9645  if (rv == ERR_IO_PENDING)
9646    rv = callback.WaitForResult();
9647  EXPECT_EQ(3, rv);
9648  rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
9649  EXPECT_EQ(0, rv);
9650  // There are still 0 idle sockets, since the trans_compete transaction
9651  // will be handed it immediately after trans releases it to the group.
9652  EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
9653
9654  // The competing request can now finish. Wait for the headers and then
9655  // read the body.
9656  rv = callback_compete.WaitForResult();
9657  EXPECT_EQ(OK, rv);
9658  rv = trans_compete->Read(io_buf.get(), io_buf->size(), callback.callback());
9659  if (rv == ERR_IO_PENDING)
9660    rv = callback.WaitForResult();
9661  EXPECT_EQ(3, rv);
9662  rv = trans_compete->Read(io_buf.get(), io_buf->size(), callback.callback());
9663  EXPECT_EQ(0, rv);
9664
9665  // Finally, the socket is released to the group.
9666  EXPECT_EQ(1, transport_pool->IdleSocketCountInGroup(kSocketGroup));
9667}
9668
9669// This tests the case that a request is issued via http instead of spdy after
9670// npn is negotiated.
9671TEST_P(HttpNetworkTransactionTest, NpnWithHttpOverSSL) {
9672  HttpStreamFactory::set_use_alternate_protocols(true);
9673  std::vector<NextProto> next_protos;
9674  next_protos.push_back(kProtoHTTP11);
9675  HttpStreamFactory::SetNextProtos(next_protos);
9676  HttpRequestInfo request;
9677  request.method = "GET";
9678  request.url = GURL("https://www.google.com/");
9679  request.load_flags = 0;
9680
9681  MockWrite data_writes[] = {
9682    MockWrite("GET / HTTP/1.1\r\n"
9683              "Host: www.google.com\r\n"
9684              "Connection: keep-alive\r\n\r\n"),
9685  };
9686
9687  std::string alternate_protocol_http_header =
9688      GetAlternateProtocolHttpHeader();
9689
9690  MockRead data_reads[] = {
9691    MockRead("HTTP/1.1 200 OK\r\n"),
9692    MockRead(alternate_protocol_http_header.c_str()),
9693    MockRead("hello world"),
9694    MockRead(SYNCHRONOUS, OK),
9695  };
9696
9697  SSLSocketDataProvider ssl(ASYNC, OK);
9698  ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
9699  ssl.next_proto = "http/1.1";
9700  ssl.protocol_negotiated = kProtoHTTP11;
9701
9702  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9703
9704  StaticSocketDataProvider data(data_reads, arraysize(data_reads),
9705                                data_writes, arraysize(data_writes));
9706  session_deps_.socket_factory->AddSocketDataProvider(&data);
9707
9708  TestCompletionCallback callback;
9709
9710  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9711  scoped_ptr<HttpTransaction> trans(
9712      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9713
9714  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9715
9716  EXPECT_EQ(ERR_IO_PENDING, rv);
9717  EXPECT_EQ(OK, callback.WaitForResult());
9718
9719  const HttpResponseInfo* response = trans->GetResponseInfo();
9720  ASSERT_TRUE(response != NULL);
9721  ASSERT_TRUE(response->headers.get() != NULL);
9722  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9723
9724  std::string response_data;
9725  ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9726  EXPECT_EQ("hello world", response_data);
9727
9728  EXPECT_FALSE(response->was_fetched_via_spdy);
9729  EXPECT_TRUE(response->was_npn_negotiated);
9730}
9731
9732TEST_P(HttpNetworkTransactionTest, SpdyPostNPNServerHangup) {
9733  // Simulate the SSL handshake completing with an NPN negotiation
9734  // followed by an immediate server closing of the socket.
9735  // Fix crash:  http://crbug.com/46369
9736  HttpStreamFactory::set_use_alternate_protocols(true);
9737  HttpStreamFactory::SetNextProtos(SpdyNextProtos());
9738
9739  HttpRequestInfo request;
9740  request.method = "GET";
9741  request.url = GURL("https://www.google.com/");
9742  request.load_flags = 0;
9743
9744  SSLSocketDataProvider ssl(ASYNC, OK);
9745  ssl.SetNextProto(GetParam());
9746  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9747
9748  scoped_ptr<SpdyFrame> req(
9749      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
9750  MockWrite spdy_writes[] = { CreateMockWrite(*req) };
9751
9752  MockRead spdy_reads[] = {
9753    MockRead(SYNCHRONOUS, 0, 0)   // Not async - return 0 immediately.
9754  };
9755
9756  DelayedSocketData spdy_data(
9757      0,  // don't wait in this case, immediate hangup.
9758      spdy_reads, arraysize(spdy_reads),
9759      spdy_writes, arraysize(spdy_writes));
9760  session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
9761
9762  TestCompletionCallback callback;
9763
9764  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9765  scoped_ptr<HttpTransaction> trans(
9766      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9767
9768  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9769  EXPECT_EQ(ERR_IO_PENDING, rv);
9770  EXPECT_EQ(ERR_CONNECTION_CLOSED, callback.WaitForResult());
9771}
9772
9773// A subclass of HttpAuthHandlerMock that records the request URL when
9774// it gets it. This is needed since the auth handler may get destroyed
9775// before we get a chance to query it.
9776class UrlRecordingHttpAuthHandlerMock : public HttpAuthHandlerMock {
9777 public:
9778  explicit UrlRecordingHttpAuthHandlerMock(GURL* url) : url_(url) {}
9779
9780  virtual ~UrlRecordingHttpAuthHandlerMock() {}
9781
9782 protected:
9783  virtual int GenerateAuthTokenImpl(const AuthCredentials* credentials,
9784                                    const HttpRequestInfo* request,
9785                                    const CompletionCallback& callback,
9786                                    std::string* auth_token) OVERRIDE {
9787    *url_ = request->url;
9788    return HttpAuthHandlerMock::GenerateAuthTokenImpl(
9789        credentials, request, callback, auth_token);
9790  }
9791
9792 private:
9793  GURL* url_;
9794};
9795
9796TEST_P(HttpNetworkTransactionTest, SpdyAlternateProtocolThroughProxy) {
9797  // This test ensures that the URL passed into the proxy is upgraded
9798  // to https when doing an Alternate Protocol upgrade.
9799  HttpStreamFactory::set_use_alternate_protocols(true);
9800  HttpStreamFactory::SetNextProtos(SpdyNextProtos());
9801
9802  session_deps_.proxy_service.reset(
9803      ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
9804  CapturingNetLog net_log;
9805  session_deps_.net_log = &net_log;
9806  GURL request_url;
9807  {
9808    HttpAuthHandlerMock::Factory* auth_factory =
9809        new HttpAuthHandlerMock::Factory();
9810    UrlRecordingHttpAuthHandlerMock* auth_handler =
9811        new UrlRecordingHttpAuthHandlerMock(&request_url);
9812    auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_PROXY);
9813    auth_factory->set_do_init_from_challenge(true);
9814    session_deps_.http_auth_handler_factory.reset(auth_factory);
9815  }
9816
9817  HttpRequestInfo request;
9818  request.method = "GET";
9819  request.url = GURL("http://www.google.com");
9820  request.load_flags = 0;
9821
9822  // First round goes unauthenticated through the proxy.
9823  MockWrite data_writes_1[] = {
9824    MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
9825              "Host: www.google.com\r\n"
9826              "Proxy-Connection: keep-alive\r\n"
9827              "\r\n"),
9828  };
9829  MockRead data_reads_1[] = {
9830    MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
9831    MockRead("HTTP/1.1 200 OK\r\n"
9832             "Alternate-Protocol: 443:npn-spdy/2\r\n"
9833             "Proxy-Connection: close\r\n"
9834             "\r\n"),
9835  };
9836  StaticSocketDataProvider data_1(data_reads_1, arraysize(data_reads_1),
9837                                  data_writes_1, arraysize(data_writes_1));
9838
9839  // Second round tries to tunnel to www.google.com due to the
9840  // Alternate-Protocol announcement in the first round. It fails due
9841  // to a proxy authentication challenge.
9842  // After the failure, a tunnel is established to www.google.com using
9843  // Proxy-Authorization headers. There is then a SPDY request round.
9844  //
9845  // NOTE: Despite the "Proxy-Connection: Close", these are done on the
9846  // same MockTCPClientSocket since the underlying HttpNetworkClientSocket
9847  // does a Disconnect and Connect on the same socket, rather than trying
9848  // to obtain a new one.
9849  //
9850  // NOTE: Originally, the proxy response to the second CONNECT request
9851  // simply returned another 407 so the unit test could skip the SSL connection
9852  // establishment and SPDY framing issues. Alas, the
9853  // retry-http-when-alternate-protocol fails logic kicks in, which was more
9854  // complicated to set up expectations for than the SPDY session.
9855
9856  scoped_ptr<SpdyFrame> req(
9857      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
9858  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
9859  scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
9860
9861  MockWrite data_writes_2[] = {
9862    // First connection attempt without Proxy-Authorization.
9863    MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
9864              "Host: www.google.com\r\n"
9865              "Proxy-Connection: keep-alive\r\n"
9866              "\r\n"),
9867
9868    // Second connection attempt with Proxy-Authorization.
9869    MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
9870              "Host: www.google.com\r\n"
9871              "Proxy-Connection: keep-alive\r\n"
9872              "Proxy-Authorization: auth_token\r\n"
9873              "\r\n"),
9874
9875    // SPDY request
9876    CreateMockWrite(*req),
9877  };
9878  const char kRejectConnectResponse[] = ("HTTP/1.1 407 Unauthorized\r\n"
9879                                         "Proxy-Authenticate: Mock\r\n"
9880                                         "Proxy-Connection: close\r\n"
9881                                         "\r\n");
9882  const char kAcceptConnectResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
9883  MockRead data_reads_2[] = {
9884    // First connection attempt fails
9885    MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ, 1),
9886    MockRead(ASYNC, kRejectConnectResponse,
9887             arraysize(kRejectConnectResponse) - 1, 1),
9888
9889    // Second connection attempt passes
9890    MockRead(ASYNC, kAcceptConnectResponse,
9891             arraysize(kAcceptConnectResponse) -1, 4),
9892
9893    // SPDY response
9894    CreateMockRead(*resp.get(), 6),
9895    CreateMockRead(*data.get(), 6),
9896    MockRead(ASYNC, 0, 0, 6),
9897  };
9898  OrderedSocketData data_2(
9899      data_reads_2, arraysize(data_reads_2),
9900      data_writes_2, arraysize(data_writes_2));
9901
9902  SSLSocketDataProvider ssl(ASYNC, OK);
9903  ssl.SetNextProto(GetParam());
9904
9905  MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
9906  StaticSocketDataProvider hanging_non_alternate_protocol_socket(
9907      NULL, 0, NULL, 0);
9908  hanging_non_alternate_protocol_socket.set_connect_data(
9909      never_finishing_connect);
9910
9911  session_deps_.socket_factory->AddSocketDataProvider(&data_1);
9912  session_deps_.socket_factory->AddSocketDataProvider(&data_2);
9913  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9914  session_deps_.socket_factory->AddSocketDataProvider(
9915      &hanging_non_alternate_protocol_socket);
9916  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9917
9918  // First round should work and provide the Alternate-Protocol state.
9919  TestCompletionCallback callback_1;
9920  scoped_ptr<HttpTransaction> trans_1(
9921      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9922  int rv = trans_1->Start(&request, callback_1.callback(), BoundNetLog());
9923  EXPECT_EQ(ERR_IO_PENDING, rv);
9924  EXPECT_EQ(OK, callback_1.WaitForResult());
9925
9926  // Second round should attempt a tunnel connect and get an auth challenge.
9927  TestCompletionCallback callback_2;
9928  scoped_ptr<HttpTransaction> trans_2(
9929      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9930  rv = trans_2->Start(&request, callback_2.callback(), BoundNetLog());
9931  EXPECT_EQ(ERR_IO_PENDING, rv);
9932  EXPECT_EQ(OK, callback_2.WaitForResult());
9933  const HttpResponseInfo* response = trans_2->GetResponseInfo();
9934  ASSERT_TRUE(response != NULL);
9935  ASSERT_FALSE(response->auth_challenge.get() == NULL);
9936
9937  // Restart with auth. Tunnel should work and response received.
9938  TestCompletionCallback callback_3;
9939  rv = trans_2->RestartWithAuth(
9940      AuthCredentials(kFoo, kBar), callback_3.callback());
9941  EXPECT_EQ(ERR_IO_PENDING, rv);
9942  EXPECT_EQ(OK, callback_3.WaitForResult());
9943
9944  // After all that work, these two lines (or actually, just the scheme) are
9945  // what this test is all about. Make sure it happens correctly.
9946  EXPECT_EQ("https", request_url.scheme());
9947  EXPECT_EQ("www.google.com", request_url.host());
9948
9949  LoadTimingInfo load_timing_info;
9950  EXPECT_TRUE(trans_2->GetLoadTimingInfo(&load_timing_info));
9951  TestLoadTimingNotReusedWithPac(load_timing_info,
9952                                 CONNECT_TIMING_HAS_SSL_TIMES);
9953}
9954
9955// Test that if we cancel the transaction as the connection is completing, that
9956// everything tears down correctly.
9957TEST_P(HttpNetworkTransactionTest, SimpleCancel) {
9958  // Setup everything about the connection to complete synchronously, so that
9959  // after calling HttpNetworkTransaction::Start, the only thing we're waiting
9960  // for is the callback from the HttpStreamRequest.
9961  // Then cancel the transaction.
9962  // Verify that we don't crash.
9963  MockConnect mock_connect(SYNCHRONOUS, OK);
9964  MockRead data_reads[] = {
9965    MockRead(SYNCHRONOUS, "HTTP/1.0 200 OK\r\n\r\n"),
9966    MockRead(SYNCHRONOUS, "hello world"),
9967    MockRead(SYNCHRONOUS, OK),
9968  };
9969
9970  HttpRequestInfo request;
9971  request.method = "GET";
9972  request.url = GURL("http://www.google.com/");
9973  request.load_flags = 0;
9974
9975  session_deps_.host_resolver->set_synchronous_mode(true);
9976  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9977  scoped_ptr<HttpTransaction> trans(
9978      new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
9979
9980  StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
9981  data.set_connect_data(mock_connect);
9982  session_deps_.socket_factory->AddSocketDataProvider(&data);
9983
9984  TestCompletionCallback callback;
9985
9986  CapturingBoundNetLog log;
9987  int rv = trans->Start(&request, callback.callback(), log.bound());
9988  EXPECT_EQ(ERR_IO_PENDING, rv);
9989  trans.reset();  // Cancel the transaction here.
9990
9991  base::MessageLoop::current()->RunUntilIdle();
9992}
9993
9994// Test a basic GET request through a proxy.
9995TEST_P(HttpNetworkTransactionTest, ProxyGet) {
9996  session_deps_.proxy_service.reset(
9997      ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
9998  CapturingBoundNetLog log;
9999  session_deps_.net_log = log.bound().net_log();
10000  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10001
10002  HttpRequestInfo request;
10003  request.method = "GET";
10004  request.url = GURL("http://www.google.com/");
10005
10006  MockWrite data_writes1[] = {
10007    MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
10008              "Host: www.google.com\r\n"
10009              "Proxy-Connection: keep-alive\r\n\r\n"),
10010  };
10011
10012  MockRead data_reads1[] = {
10013    MockRead("HTTP/1.1 200 OK\r\n"),
10014    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10015    MockRead("Content-Length: 100\r\n\r\n"),
10016    MockRead(SYNCHRONOUS, OK),
10017  };
10018
10019  StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
10020                                 data_writes1, arraysize(data_writes1));
10021  session_deps_.socket_factory->AddSocketDataProvider(&data1);
10022
10023  TestCompletionCallback callback1;
10024
10025  scoped_ptr<HttpTransaction> trans(
10026      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10027
10028  int rv = trans->Start(&request, callback1.callback(), log.bound());
10029  EXPECT_EQ(ERR_IO_PENDING, rv);
10030
10031  rv = callback1.WaitForResult();
10032  EXPECT_EQ(OK, rv);
10033
10034  const HttpResponseInfo* response = trans->GetResponseInfo();
10035  ASSERT_TRUE(response != NULL);
10036
10037  EXPECT_TRUE(response->headers->IsKeepAlive());
10038  EXPECT_EQ(200, response->headers->response_code());
10039  EXPECT_EQ(100, response->headers->GetContentLength());
10040  EXPECT_TRUE(response->was_fetched_via_proxy);
10041  EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
10042
10043  LoadTimingInfo load_timing_info;
10044  EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
10045  TestLoadTimingNotReusedWithPac(load_timing_info,
10046                                 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
10047}
10048
10049// Test a basic HTTPS GET request through a proxy.
10050TEST_P(HttpNetworkTransactionTest, ProxyTunnelGet) {
10051  session_deps_.proxy_service.reset(
10052      ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
10053  CapturingBoundNetLog log;
10054  session_deps_.net_log = log.bound().net_log();
10055  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10056
10057  HttpRequestInfo request;
10058  request.method = "GET";
10059  request.url = GURL("https://www.google.com/");
10060
10061  // Since we have proxy, should try to establish tunnel.
10062  MockWrite data_writes1[] = {
10063    MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
10064              "Host: www.google.com\r\n"
10065              "Proxy-Connection: keep-alive\r\n\r\n"),
10066
10067    MockWrite("GET / HTTP/1.1\r\n"
10068              "Host: www.google.com\r\n"
10069              "Connection: keep-alive\r\n\r\n"),
10070  };
10071
10072  MockRead data_reads1[] = {
10073    MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
10074
10075    MockRead("HTTP/1.1 200 OK\r\n"),
10076    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10077    MockRead("Content-Length: 100\r\n\r\n"),
10078    MockRead(SYNCHRONOUS, OK),
10079  };
10080
10081  StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
10082                                 data_writes1, arraysize(data_writes1));
10083  session_deps_.socket_factory->AddSocketDataProvider(&data1);
10084  SSLSocketDataProvider ssl(ASYNC, OK);
10085  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10086
10087  TestCompletionCallback callback1;
10088
10089  scoped_ptr<HttpTransaction> trans(
10090      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10091
10092  int rv = trans->Start(&request, callback1.callback(), log.bound());
10093  EXPECT_EQ(ERR_IO_PENDING, rv);
10094
10095  rv = callback1.WaitForResult();
10096  EXPECT_EQ(OK, rv);
10097  net::CapturingNetLog::CapturedEntryList entries;
10098  log.GetEntries(&entries);
10099  size_t pos = ExpectLogContainsSomewhere(
10100      entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
10101      NetLog::PHASE_NONE);
10102  ExpectLogContainsSomewhere(
10103      entries, pos,
10104      NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
10105      NetLog::PHASE_NONE);
10106
10107  const HttpResponseInfo* response = trans->GetResponseInfo();
10108  ASSERT_TRUE(response != NULL);
10109
10110  EXPECT_TRUE(response->headers->IsKeepAlive());
10111  EXPECT_EQ(200, response->headers->response_code());
10112  EXPECT_EQ(100, response->headers->GetContentLength());
10113  EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
10114  EXPECT_TRUE(response->was_fetched_via_proxy);
10115
10116  LoadTimingInfo load_timing_info;
10117  EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
10118  TestLoadTimingNotReusedWithPac(load_timing_info,
10119                                 CONNECT_TIMING_HAS_SSL_TIMES);
10120}
10121
10122// Test a basic HTTPS GET request through a proxy, but the server hangs up
10123// while establishing the tunnel.
10124TEST_P(HttpNetworkTransactionTest, ProxyTunnelGetHangup) {
10125  session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
10126  CapturingBoundNetLog log;
10127  session_deps_.net_log = log.bound().net_log();
10128  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10129
10130  HttpRequestInfo request;
10131  request.method = "GET";
10132  request.url = GURL("https://www.google.com/");
10133
10134  // Since we have proxy, should try to establish tunnel.
10135  MockWrite data_writes1[] = {
10136    MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
10137              "Host: www.google.com\r\n"
10138              "Proxy-Connection: keep-alive\r\n\r\n"),
10139
10140    MockWrite("GET / HTTP/1.1\r\n"
10141              "Host: www.google.com\r\n"
10142              "Connection: keep-alive\r\n\r\n"),
10143  };
10144
10145  MockRead data_reads1[] = {
10146    MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
10147    MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
10148    MockRead(ASYNC, 0, 0),  // EOF
10149  };
10150
10151  StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
10152                                 data_writes1, arraysize(data_writes1));
10153  session_deps_.socket_factory->AddSocketDataProvider(&data1);
10154  SSLSocketDataProvider ssl(ASYNC, OK);
10155  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10156
10157  TestCompletionCallback callback1;
10158
10159  scoped_ptr<HttpTransaction> trans(
10160      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10161
10162  int rv = trans->Start(&request, callback1.callback(), log.bound());
10163  EXPECT_EQ(ERR_IO_PENDING, rv);
10164
10165  rv = callback1.WaitForResult();
10166  EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
10167  net::CapturingNetLog::CapturedEntryList entries;
10168  log.GetEntries(&entries);
10169  size_t pos = ExpectLogContainsSomewhere(
10170      entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
10171      NetLog::PHASE_NONE);
10172  ExpectLogContainsSomewhere(
10173      entries, pos,
10174      NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
10175      NetLog::PHASE_NONE);
10176}
10177
10178// Test for crbug.com/55424.
10179TEST_P(HttpNetworkTransactionTest, PreconnectWithExistingSpdySession) {
10180  scoped_ptr<SpdyFrame> req(
10181      spdy_util_.ConstructSpdyGet("https://www.google.com", false, 1, LOWEST));
10182  MockWrite spdy_writes[] = { CreateMockWrite(*req) };
10183
10184  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
10185  scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
10186  MockRead spdy_reads[] = {
10187    CreateMockRead(*resp),
10188    CreateMockRead(*data),
10189    MockRead(ASYNC, 0, 0),
10190  };
10191
10192  DelayedSocketData spdy_data(
10193      1,  // wait for one write to finish before reading.
10194      spdy_reads, arraysize(spdy_reads),
10195      spdy_writes, arraysize(spdy_writes));
10196  session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
10197
10198  SSLSocketDataProvider ssl(ASYNC, OK);
10199  ssl.SetNextProto(GetParam());
10200  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10201
10202  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10203
10204  // Set up an initial SpdySession in the pool to reuse.
10205  HostPortPair host_port_pair("www.google.com", 443);
10206  SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
10207                     kPrivacyModeDisabled);
10208  base::WeakPtr<SpdySession> spdy_session =
10209      CreateInsecureSpdySession(session, key, BoundNetLog());
10210
10211  HttpRequestInfo request;
10212  request.method = "GET";
10213  request.url = GURL("https://www.google.com/");
10214  request.load_flags = 0;
10215
10216  // This is the important line that marks this as a preconnect.
10217  request.motivation = HttpRequestInfo::PRECONNECT_MOTIVATED;
10218
10219  scoped_ptr<HttpTransaction> trans(
10220      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10221
10222  TestCompletionCallback callback;
10223  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
10224  EXPECT_EQ(ERR_IO_PENDING, rv);
10225  EXPECT_EQ(OK, callback.WaitForResult());
10226}
10227
10228// Given a net error, cause that error to be returned from the first Write()
10229// call and verify that the HttpTransaction fails with that error.
10230void HttpNetworkTransactionTest::CheckErrorIsPassedBack(
10231    int error, IoMode mode) {
10232  net::HttpRequestInfo request_info;
10233  request_info.url = GURL("https://www.example.com/");
10234  request_info.method = "GET";
10235  request_info.load_flags = net::LOAD_NORMAL;
10236
10237  SSLSocketDataProvider ssl_data(mode, OK);
10238  net::MockWrite data_writes[] = {
10239    net::MockWrite(mode, error),
10240  };
10241  net::StaticSocketDataProvider data(NULL, 0,
10242                                     data_writes, arraysize(data_writes));
10243  session_deps_.socket_factory->AddSocketDataProvider(&data);
10244  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data);
10245
10246  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10247  scoped_ptr<HttpTransaction> trans(
10248      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10249
10250  TestCompletionCallback callback;
10251  int rv = trans->Start(&request_info, callback.callback(), net::BoundNetLog());
10252  if (rv == net::ERR_IO_PENDING)
10253    rv = callback.WaitForResult();
10254  ASSERT_EQ(error, rv);
10255}
10256
10257TEST_P(HttpNetworkTransactionTest, SSLWriteCertError) {
10258  // Just check a grab bag of cert errors.
10259  static const int kErrors[] = {
10260    ERR_CERT_COMMON_NAME_INVALID,
10261    ERR_CERT_AUTHORITY_INVALID,
10262    ERR_CERT_DATE_INVALID,
10263  };
10264  for (size_t i = 0; i < arraysize(kErrors); i++) {
10265    CheckErrorIsPassedBack(kErrors[i], ASYNC);
10266    CheckErrorIsPassedBack(kErrors[i], SYNCHRONOUS);
10267  }
10268}
10269
10270// Ensure that a client certificate is removed from the SSL client auth
10271// cache when:
10272//  1) No proxy is involved.
10273//  2) TLS False Start is disabled.
10274//  3) The initial TLS handshake requests a client certificate.
10275//  4) The client supplies an invalid/unacceptable certificate.
10276TEST_P(HttpNetworkTransactionTest,
10277       ClientAuthCertCache_Direct_NoFalseStart) {
10278  net::HttpRequestInfo request_info;
10279  request_info.url = GURL("https://www.example.com/");
10280  request_info.method = "GET";
10281  request_info.load_flags = net::LOAD_NORMAL;
10282
10283  scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
10284  cert_request->host_and_port = HostPortPair("www.example.com", 443);
10285
10286  // [ssl_]data1 contains the data for the first SSL handshake. When a
10287  // CertificateRequest is received for the first time, the handshake will
10288  // be aborted to allow the caller to provide a certificate.
10289  SSLSocketDataProvider ssl_data1(ASYNC, net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
10290  ssl_data1.cert_request_info = cert_request.get();
10291  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
10292  net::StaticSocketDataProvider data1(NULL, 0, NULL, 0);
10293  session_deps_.socket_factory->AddSocketDataProvider(&data1);
10294
10295  // [ssl_]data2 contains the data for the second SSL handshake. When TLS
10296  // False Start is not being used, the result of the SSL handshake will be
10297  // returned as part of the SSLClientSocket::Connect() call. This test
10298  // matches the result of a server sending a handshake_failure alert,
10299  // rather than a Finished message, because it requires a client
10300  // certificate and none was supplied.
10301  SSLSocketDataProvider ssl_data2(ASYNC, net::ERR_SSL_PROTOCOL_ERROR);
10302  ssl_data2.cert_request_info = cert_request.get();
10303  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
10304  net::StaticSocketDataProvider data2(NULL, 0, NULL, 0);
10305  session_deps_.socket_factory->AddSocketDataProvider(&data2);
10306
10307  // [ssl_]data3 contains the data for the third SSL handshake. When a
10308  // connection to a server fails during an SSL handshake,
10309  // HttpNetworkTransaction will attempt to fallback to TLSv1 if the previous
10310  // connection was attempted with TLSv1.1. This is transparent to the caller
10311  // of the HttpNetworkTransaction. Because this test failure is due to
10312  // requiring a client certificate, this fallback handshake should also
10313  // fail.
10314  SSLSocketDataProvider ssl_data3(ASYNC, net::ERR_SSL_PROTOCOL_ERROR);
10315  ssl_data3.cert_request_info = cert_request.get();
10316  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
10317  net::StaticSocketDataProvider data3(NULL, 0, NULL, 0);
10318  session_deps_.socket_factory->AddSocketDataProvider(&data3);
10319
10320  // [ssl_]data4 contains the data for the fourth SSL handshake. When a
10321  // connection to a server fails during an SSL handshake,
10322  // HttpNetworkTransaction will attempt to fallback to SSLv3 if the previous
10323  // connection was attempted with TLSv1. This is transparent to the caller
10324  // of the HttpNetworkTransaction. Because this test failure is due to
10325  // requiring a client certificate, this fallback handshake should also
10326  // fail.
10327  SSLSocketDataProvider ssl_data4(ASYNC, net::ERR_SSL_PROTOCOL_ERROR);
10328  ssl_data4.cert_request_info = cert_request.get();
10329  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data4);
10330  net::StaticSocketDataProvider data4(NULL, 0, NULL, 0);
10331  session_deps_.socket_factory->AddSocketDataProvider(&data4);
10332
10333  // Need one more if TLSv1.2 is enabled.
10334  SSLSocketDataProvider ssl_data5(ASYNC, net::ERR_SSL_PROTOCOL_ERROR);
10335  ssl_data5.cert_request_info = cert_request.get();
10336  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data5);
10337  net::StaticSocketDataProvider data5(NULL, 0, NULL, 0);
10338  session_deps_.socket_factory->AddSocketDataProvider(&data5);
10339
10340  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10341  scoped_ptr<HttpTransaction> trans(
10342      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10343
10344  // Begin the SSL handshake with the peer. This consumes ssl_data1.
10345  TestCompletionCallback callback;
10346  int rv = trans->Start(&request_info, callback.callback(), net::BoundNetLog());
10347  ASSERT_EQ(net::ERR_IO_PENDING, rv);
10348
10349  // Complete the SSL handshake, which should abort due to requiring a
10350  // client certificate.
10351  rv = callback.WaitForResult();
10352  ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
10353
10354  // Indicate that no certificate should be supplied. From the perspective
10355  // of SSLClientCertCache, NULL is just as meaningful as a real
10356  // certificate, so this is the same as supply a
10357  // legitimate-but-unacceptable certificate.
10358  rv = trans->RestartWithCertificate(NULL, callback.callback());
10359  ASSERT_EQ(net::ERR_IO_PENDING, rv);
10360
10361  // Ensure the certificate was added to the client auth cache before
10362  // allowing the connection to continue restarting.
10363  scoped_refptr<X509Certificate> client_cert;
10364  ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup(
10365      HostPortPair("www.example.com", 443), &client_cert));
10366  ASSERT_EQ(NULL, client_cert.get());
10367
10368  // Restart the handshake. This will consume ssl_data2, which fails, and
10369  // then consume ssl_data3 and ssl_data4, both of which should also fail.
10370  // The result code is checked against what ssl_data4 should return.
10371  rv = callback.WaitForResult();
10372  ASSERT_EQ(net::ERR_SSL_PROTOCOL_ERROR, rv);
10373
10374  // Ensure that the client certificate is removed from the cache on a
10375  // handshake failure.
10376  ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
10377      HostPortPair("www.example.com", 443), &client_cert));
10378}
10379
10380// Ensure that a client certificate is removed from the SSL client auth
10381// cache when:
10382//  1) No proxy is involved.
10383//  2) TLS False Start is enabled.
10384//  3) The initial TLS handshake requests a client certificate.
10385//  4) The client supplies an invalid/unacceptable certificate.
10386TEST_P(HttpNetworkTransactionTest,
10387       ClientAuthCertCache_Direct_FalseStart) {
10388  net::HttpRequestInfo request_info;
10389  request_info.url = GURL("https://www.example.com/");
10390  request_info.method = "GET";
10391  request_info.load_flags = net::LOAD_NORMAL;
10392
10393  scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
10394  cert_request->host_and_port = HostPortPair("www.example.com", 443);
10395
10396  // When TLS False Start is used, SSLClientSocket::Connect() calls will
10397  // return successfully after reading up to the peer's Certificate message.
10398  // This is to allow the caller to call SSLClientSocket::Write(), which can
10399  // enqueue application data to be sent in the same packet as the
10400  // ChangeCipherSpec and Finished messages.
10401  // The actual handshake will be finished when SSLClientSocket::Read() is
10402  // called, which expects to process the peer's ChangeCipherSpec and
10403  // Finished messages. If there was an error negotiating with the peer,
10404  // such as due to the peer requiring a client certificate when none was
10405  // supplied, the alert sent by the peer won't be processed until Read() is
10406  // called.
10407
10408  // Like the non-False Start case, when a client certificate is requested by
10409  // the peer, the handshake is aborted during the Connect() call.
10410  // [ssl_]data1 represents the initial SSL handshake with the peer.
10411  SSLSocketDataProvider ssl_data1(ASYNC, net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
10412  ssl_data1.cert_request_info = cert_request.get();
10413  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
10414  net::StaticSocketDataProvider data1(NULL, 0, NULL, 0);
10415  session_deps_.socket_factory->AddSocketDataProvider(&data1);
10416
10417  // When a client certificate is supplied, Connect() will not be aborted
10418  // when the peer requests the certificate. Instead, the handshake will
10419  // artificially succeed, allowing the caller to write the HTTP request to
10420  // the socket. The handshake messages are not processed until Read() is
10421  // called, which then detects that the handshake was aborted, due to the
10422  // peer sending a handshake_failure because it requires a client
10423  // certificate.
10424  SSLSocketDataProvider ssl_data2(ASYNC, net::OK);
10425  ssl_data2.cert_request_info = cert_request.get();
10426  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
10427  net::MockRead data2_reads[] = {
10428    net::MockRead(ASYNC /* async */, net::ERR_SSL_PROTOCOL_ERROR),
10429  };
10430  net::StaticSocketDataProvider data2(
10431      data2_reads, arraysize(data2_reads), NULL, 0);
10432  session_deps_.socket_factory->AddSocketDataProvider(&data2);
10433
10434  // As described in ClientAuthCertCache_Direct_NoFalseStart, [ssl_]data3 is
10435  // the data for the SSL handshake once the TLSv1.1 connection falls back to
10436  // TLSv1. It has the same behaviour as [ssl_]data2.
10437  SSLSocketDataProvider ssl_data3(ASYNC, net::OK);
10438  ssl_data3.cert_request_info = cert_request.get();
10439  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
10440  net::StaticSocketDataProvider data3(
10441      data2_reads, arraysize(data2_reads), NULL, 0);
10442  session_deps_.socket_factory->AddSocketDataProvider(&data3);
10443
10444  // [ssl_]data4 is the data for the SSL handshake once the TLSv1 connection
10445  // falls back to SSLv3. It has the same behaviour as [ssl_]data2.
10446  SSLSocketDataProvider ssl_data4(ASYNC, net::OK);
10447  ssl_data4.cert_request_info = cert_request.get();
10448  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data4);
10449  net::StaticSocketDataProvider data4(
10450      data2_reads, arraysize(data2_reads), NULL, 0);
10451  session_deps_.socket_factory->AddSocketDataProvider(&data4);
10452
10453  // Need one more if TLSv1.2 is enabled.
10454  SSLSocketDataProvider ssl_data5(ASYNC, net::OK);
10455  ssl_data5.cert_request_info = cert_request.get();
10456  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data5);
10457  net::StaticSocketDataProvider data5(
10458      data2_reads, arraysize(data2_reads), NULL, 0);
10459  session_deps_.socket_factory->AddSocketDataProvider(&data5);
10460
10461  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10462  scoped_ptr<HttpTransaction> trans(
10463      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10464
10465  // Begin the initial SSL handshake.
10466  TestCompletionCallback callback;
10467  int rv = trans->Start(&request_info, callback.callback(), net::BoundNetLog());
10468  ASSERT_EQ(net::ERR_IO_PENDING, rv);
10469
10470  // Complete the SSL handshake, which should abort due to requiring a
10471  // client certificate.
10472  rv = callback.WaitForResult();
10473  ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
10474
10475  // Indicate that no certificate should be supplied. From the perspective
10476  // of SSLClientCertCache, NULL is just as meaningful as a real
10477  // certificate, so this is the same as supply a
10478  // legitimate-but-unacceptable certificate.
10479  rv = trans->RestartWithCertificate(NULL, callback.callback());
10480  ASSERT_EQ(net::ERR_IO_PENDING, rv);
10481
10482  // Ensure the certificate was added to the client auth cache before
10483  // allowing the connection to continue restarting.
10484  scoped_refptr<X509Certificate> client_cert;
10485  ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup(
10486      HostPortPair("www.example.com", 443), &client_cert));
10487  ASSERT_EQ(NULL, client_cert.get());
10488
10489  // Restart the handshake. This will consume ssl_data2, which fails, and
10490  // then consume ssl_data3 and ssl_data4, both of which should also fail.
10491  // The result code is checked against what ssl_data4 should return.
10492  rv = callback.WaitForResult();
10493  ASSERT_EQ(net::ERR_SSL_PROTOCOL_ERROR, rv);
10494
10495  // Ensure that the client certificate is removed from the cache on a
10496  // handshake failure.
10497  ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
10498      HostPortPair("www.example.com", 443), &client_cert));
10499}
10500
10501// Ensure that a client certificate is removed from the SSL client auth
10502// cache when:
10503//  1) An HTTPS proxy is involved.
10504//  3) The HTTPS proxy requests a client certificate.
10505//  4) The client supplies an invalid/unacceptable certificate for the
10506//     proxy.
10507// The test is repeated twice, first for connecting to an HTTPS endpoint,
10508// then for connecting to an HTTP endpoint.
10509TEST_P(HttpNetworkTransactionTest, ClientAuthCertCache_Proxy_Fail) {
10510  session_deps_.proxy_service.reset(
10511      ProxyService::CreateFixed("https://proxy:70"));
10512  CapturingBoundNetLog log;
10513  session_deps_.net_log = log.bound().net_log();
10514
10515  scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
10516  cert_request->host_and_port = HostPortPair("proxy", 70);
10517
10518  // See ClientAuthCertCache_Direct_NoFalseStart for the explanation of
10519  // [ssl_]data[1-3]. Rather than represending the endpoint
10520  // (www.example.com:443), they represent failures with the HTTPS proxy
10521  // (proxy:70).
10522  SSLSocketDataProvider ssl_data1(ASYNC, net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
10523  ssl_data1.cert_request_info = cert_request.get();
10524  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
10525  net::StaticSocketDataProvider data1(NULL, 0, NULL, 0);
10526  session_deps_.socket_factory->AddSocketDataProvider(&data1);
10527
10528  SSLSocketDataProvider ssl_data2(ASYNC, net::ERR_SSL_PROTOCOL_ERROR);
10529  ssl_data2.cert_request_info = cert_request.get();
10530  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
10531  net::StaticSocketDataProvider data2(NULL, 0, NULL, 0);
10532  session_deps_.socket_factory->AddSocketDataProvider(&data2);
10533
10534  // TODO(wtc): find out why this unit test doesn't need [ssl_]data3.
10535#if 0
10536  SSLSocketDataProvider ssl_data3(ASYNC, net::ERR_SSL_PROTOCOL_ERROR);
10537  ssl_data3.cert_request_info = cert_request.get();
10538  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
10539  net::StaticSocketDataProvider data3(NULL, 0, NULL, 0);
10540  session_deps_.socket_factory->AddSocketDataProvider(&data3);
10541#endif
10542
10543  net::HttpRequestInfo requests[2];
10544  requests[0].url = GURL("https://www.example.com/");
10545  requests[0].method = "GET";
10546  requests[0].load_flags = net::LOAD_NORMAL;
10547
10548  requests[1].url = GURL("http://www.example.com/");
10549  requests[1].method = "GET";
10550  requests[1].load_flags = net::LOAD_NORMAL;
10551
10552  for (size_t i = 0; i < arraysize(requests); ++i) {
10553    session_deps_.socket_factory->ResetNextMockIndexes();
10554    scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10555    scoped_ptr<HttpNetworkTransaction> trans(
10556        new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10557
10558    // Begin the SSL handshake with the proxy.
10559    TestCompletionCallback callback;
10560    int rv = trans->Start(
10561        &requests[i], callback.callback(), net::BoundNetLog());
10562    ASSERT_EQ(net::ERR_IO_PENDING, rv);
10563
10564    // Complete the SSL handshake, which should abort due to requiring a
10565    // client certificate.
10566    rv = callback.WaitForResult();
10567    ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
10568
10569    // Indicate that no certificate should be supplied. From the perspective
10570    // of SSLClientCertCache, NULL is just as meaningful as a real
10571    // certificate, so this is the same as supply a
10572    // legitimate-but-unacceptable certificate.
10573    rv = trans->RestartWithCertificate(NULL, callback.callback());
10574    ASSERT_EQ(net::ERR_IO_PENDING, rv);
10575
10576    // Ensure the certificate was added to the client auth cache before
10577    // allowing the connection to continue restarting.
10578    scoped_refptr<X509Certificate> client_cert;
10579    ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup(
10580        HostPortPair("proxy", 70), &client_cert));
10581    ASSERT_EQ(NULL, client_cert.get());
10582    // Ensure the certificate was NOT cached for the endpoint. This only
10583    // applies to HTTPS requests, but is fine to check for HTTP requests.
10584    ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
10585        HostPortPair("www.example.com", 443), &client_cert));
10586
10587    // Restart the handshake. This will consume ssl_data2, which fails, and
10588    // then consume ssl_data3, which should also fail. The result code is
10589    // checked against what ssl_data3 should return.
10590    rv = callback.WaitForResult();
10591    ASSERT_EQ(net::ERR_PROXY_CONNECTION_FAILED, rv);
10592
10593    // Now that the new handshake has failed, ensure that the client
10594    // certificate was removed from the client auth cache.
10595    ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
10596        HostPortPair("proxy", 70), &client_cert));
10597    ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup(
10598        HostPortPair("www.example.com", 443), &client_cert));
10599  }
10600}
10601
10602// Unlike TEST/TEST_F, which are macros that expand to further macros,
10603// TEST_P is a macro that expands directly to code that stringizes the
10604// arguments. As a result, macros passed as parameters (such as prefix
10605// or test_case_name) will not be expanded by the preprocessor. To
10606// work around this, indirect the macro for TEST_P, so that the
10607// pre-processor will expand macros such as MAYBE_test_name before
10608// instantiating the test.
10609#define WRAPPED_TEST_P(test_case_name, test_name) \
10610  TEST_P(test_case_name, test_name)
10611
10612// Times out on Win7 dbg(2) bot. http://crbug.com/124776
10613#if defined(OS_WIN)
10614#define MAYBE_UseIPConnectionPooling DISABLED_UseIPConnectionPooling
10615#else
10616#define MAYBE_UseIPConnectionPooling UseIPConnectionPooling
10617#endif
10618WRAPPED_TEST_P(HttpNetworkTransactionTest, MAYBE_UseIPConnectionPooling) {
10619  HttpStreamFactory::set_use_alternate_protocols(true);
10620  HttpStreamFactory::SetNextProtos(SpdyNextProtos());
10621
10622  // Set up a special HttpNetworkSession with a MockCachingHostResolver.
10623  session_deps_.host_resolver.reset(new MockCachingHostResolver());
10624  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10625  SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
10626  pool_peer.DisableDomainAuthenticationVerification();
10627
10628  SSLSocketDataProvider ssl(ASYNC, OK);
10629  ssl.SetNextProto(GetParam());
10630  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10631
10632  scoped_ptr<SpdyFrame> host1_req(
10633      spdy_util_.ConstructSpdyGet("https://www.google.com", false, 1, LOWEST));
10634  scoped_ptr<SpdyFrame> host2_req(
10635      spdy_util_.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST));
10636  MockWrite spdy_writes[] = {
10637    CreateMockWrite(*host1_req, 1),
10638    CreateMockWrite(*host2_req, 4),
10639  };
10640  scoped_ptr<SpdyFrame> host1_resp(
10641      spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
10642  scoped_ptr<SpdyFrame> host1_resp_body(
10643      spdy_util_.ConstructSpdyBodyFrame(1, true));
10644  scoped_ptr<SpdyFrame> host2_resp(
10645      spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
10646  scoped_ptr<SpdyFrame> host2_resp_body(
10647      spdy_util_.ConstructSpdyBodyFrame(3, true));
10648  MockRead spdy_reads[] = {
10649    CreateMockRead(*host1_resp, 2),
10650    CreateMockRead(*host1_resp_body, 3),
10651    CreateMockRead(*host2_resp, 5),
10652    CreateMockRead(*host2_resp_body, 6),
10653    MockRead(ASYNC, 0, 7),
10654  };
10655
10656  IPAddressNumber ip;
10657  ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip));
10658  IPEndPoint peer_addr = IPEndPoint(ip, 443);
10659  MockConnect connect(ASYNC, OK, peer_addr);
10660  OrderedSocketData spdy_data(
10661      connect,
10662      spdy_reads, arraysize(spdy_reads),
10663      spdy_writes, arraysize(spdy_writes));
10664  session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
10665
10666  TestCompletionCallback callback;
10667  HttpRequestInfo request1;
10668  request1.method = "GET";
10669  request1.url = GURL("https://www.google.com/");
10670  request1.load_flags = 0;
10671  HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
10672
10673  int rv = trans1.Start(&request1, callback.callback(), BoundNetLog());
10674  EXPECT_EQ(ERR_IO_PENDING, rv);
10675  EXPECT_EQ(OK, callback.WaitForResult());
10676
10677  const HttpResponseInfo* response = trans1.GetResponseInfo();
10678  ASSERT_TRUE(response != NULL);
10679  ASSERT_TRUE(response->headers.get() != NULL);
10680  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10681
10682  std::string response_data;
10683  ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
10684  EXPECT_EQ("hello!", response_data);
10685
10686  // Preload www.gmail.com into HostCache.
10687  HostPortPair host_port("www.gmail.com", 443);
10688  HostResolver::RequestInfo resolve_info(host_port);
10689  AddressList ignored;
10690  rv = session_deps_.host_resolver->Resolve(resolve_info,
10691                                            DEFAULT_PRIORITY,
10692                                            &ignored,
10693                                            callback.callback(),
10694                                            NULL,
10695                                            BoundNetLog());
10696  EXPECT_EQ(ERR_IO_PENDING, rv);
10697  rv = callback.WaitForResult();
10698  EXPECT_EQ(OK, rv);
10699
10700  HttpRequestInfo request2;
10701  request2.method = "GET";
10702  request2.url = GURL("https://www.gmail.com/");
10703  request2.load_flags = 0;
10704  HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
10705
10706  rv = trans2.Start(&request2, callback.callback(), BoundNetLog());
10707  EXPECT_EQ(ERR_IO_PENDING, rv);
10708  EXPECT_EQ(OK, callback.WaitForResult());
10709
10710  response = trans2.GetResponseInfo();
10711  ASSERT_TRUE(response != NULL);
10712  ASSERT_TRUE(response->headers.get() != NULL);
10713  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10714  EXPECT_TRUE(response->was_fetched_via_spdy);
10715  EXPECT_TRUE(response->was_npn_negotiated);
10716  ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
10717  EXPECT_EQ("hello!", response_data);
10718}
10719#undef MAYBE_UseIPConnectionPooling
10720
10721TEST_P(HttpNetworkTransactionTest, UseIPConnectionPoolingAfterResolution) {
10722  HttpStreamFactory::set_use_alternate_protocols(true);
10723  HttpStreamFactory::SetNextProtos(SpdyNextProtos());
10724
10725  // Set up a special HttpNetworkSession with a MockCachingHostResolver.
10726  session_deps_.host_resolver.reset(new MockCachingHostResolver());
10727  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10728  SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
10729  pool_peer.DisableDomainAuthenticationVerification();
10730
10731  SSLSocketDataProvider ssl(ASYNC, OK);
10732  ssl.SetNextProto(GetParam());
10733  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10734
10735  scoped_ptr<SpdyFrame> host1_req(
10736      spdy_util_.ConstructSpdyGet("https://www.google.com", false, 1, LOWEST));
10737  scoped_ptr<SpdyFrame> host2_req(
10738      spdy_util_.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST));
10739  MockWrite spdy_writes[] = {
10740    CreateMockWrite(*host1_req, 1),
10741    CreateMockWrite(*host2_req, 4),
10742  };
10743  scoped_ptr<SpdyFrame> host1_resp(
10744      spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
10745  scoped_ptr<SpdyFrame> host1_resp_body(
10746      spdy_util_.ConstructSpdyBodyFrame(1, true));
10747  scoped_ptr<SpdyFrame> host2_resp(
10748      spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
10749  scoped_ptr<SpdyFrame> host2_resp_body(
10750      spdy_util_.ConstructSpdyBodyFrame(3, true));
10751  MockRead spdy_reads[] = {
10752    CreateMockRead(*host1_resp, 2),
10753    CreateMockRead(*host1_resp_body, 3),
10754    CreateMockRead(*host2_resp, 5),
10755    CreateMockRead(*host2_resp_body, 6),
10756    MockRead(ASYNC, 0, 7),
10757  };
10758
10759  IPAddressNumber ip;
10760  ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip));
10761  IPEndPoint peer_addr = IPEndPoint(ip, 443);
10762  MockConnect connect(ASYNC, OK, peer_addr);
10763  OrderedSocketData spdy_data(
10764      connect,
10765      spdy_reads, arraysize(spdy_reads),
10766      spdy_writes, arraysize(spdy_writes));
10767  session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
10768
10769  TestCompletionCallback callback;
10770  HttpRequestInfo request1;
10771  request1.method = "GET";
10772  request1.url = GURL("https://www.google.com/");
10773  request1.load_flags = 0;
10774  HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
10775
10776  int rv = trans1.Start(&request1, callback.callback(), BoundNetLog());
10777  EXPECT_EQ(ERR_IO_PENDING, rv);
10778  EXPECT_EQ(OK, callback.WaitForResult());
10779
10780  const HttpResponseInfo* response = trans1.GetResponseInfo();
10781  ASSERT_TRUE(response != NULL);
10782  ASSERT_TRUE(response->headers.get() != NULL);
10783  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10784
10785  std::string response_data;
10786  ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
10787  EXPECT_EQ("hello!", response_data);
10788
10789  HttpRequestInfo request2;
10790  request2.method = "GET";
10791  request2.url = GURL("https://www.gmail.com/");
10792  request2.load_flags = 0;
10793  HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
10794
10795  rv = trans2.Start(&request2, callback.callback(), BoundNetLog());
10796  EXPECT_EQ(ERR_IO_PENDING, rv);
10797  EXPECT_EQ(OK, callback.WaitForResult());
10798
10799  response = trans2.GetResponseInfo();
10800  ASSERT_TRUE(response != NULL);
10801  ASSERT_TRUE(response->headers.get() != NULL);
10802  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10803  EXPECT_TRUE(response->was_fetched_via_spdy);
10804  EXPECT_TRUE(response->was_npn_negotiated);
10805  ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
10806  EXPECT_EQ("hello!", response_data);
10807}
10808
10809class OneTimeCachingHostResolver : public net::HostResolver {
10810 public:
10811  explicit OneTimeCachingHostResolver(const HostPortPair& host_port)
10812      : host_port_(host_port) {}
10813  virtual ~OneTimeCachingHostResolver() {}
10814
10815  RuleBasedHostResolverProc* rules() { return host_resolver_.rules(); }
10816
10817  // HostResolver methods:
10818  virtual int Resolve(const RequestInfo& info,
10819                      RequestPriority priority,
10820                      AddressList* addresses,
10821                      const CompletionCallback& callback,
10822                      RequestHandle* out_req,
10823                      const BoundNetLog& net_log) OVERRIDE {
10824    return host_resolver_.Resolve(
10825        info, priority, addresses, callback, out_req, net_log);
10826  }
10827
10828  virtual int ResolveFromCache(const RequestInfo& info,
10829                               AddressList* addresses,
10830                               const BoundNetLog& net_log) OVERRIDE {
10831    int rv = host_resolver_.ResolveFromCache(info, addresses, net_log);
10832    if (rv == OK && info.host_port_pair().Equals(host_port_))
10833      host_resolver_.GetHostCache()->clear();
10834    return rv;
10835  }
10836
10837  virtual void CancelRequest(RequestHandle req) OVERRIDE {
10838    host_resolver_.CancelRequest(req);
10839  }
10840
10841  MockCachingHostResolver* GetMockHostResolver() {
10842    return &host_resolver_;
10843  }
10844
10845 private:
10846  MockCachingHostResolver host_resolver_;
10847  const HostPortPair host_port_;
10848};
10849
10850// Times out on Win7 dbg(2) bot. http://crbug.com/124776
10851#if defined(OS_WIN)
10852#define MAYBE_UseIPConnectionPoolingWithHostCacheExpiration \
10853    DISABLED_UseIPConnectionPoolingWithHostCacheExpiration
10854#else
10855#define MAYBE_UseIPConnectionPoolingWithHostCacheExpiration \
10856    UseIPConnectionPoolingWithHostCacheExpiration
10857#endif
10858WRAPPED_TEST_P(HttpNetworkTransactionTest,
10859               MAYBE_UseIPConnectionPoolingWithHostCacheExpiration) {
10860// Times out on Win7 dbg(2) bot. http://crbug.com/124776 . (MAYBE_
10861// prefix doesn't work with parametrized tests).
10862#if defined(OS_WIN)
10863  return;
10864#endif
10865
10866  HttpStreamFactory::set_use_alternate_protocols(true);
10867  HttpStreamFactory::SetNextProtos(SpdyNextProtos());
10868
10869  // Set up a special HttpNetworkSession with a OneTimeCachingHostResolver.
10870  OneTimeCachingHostResolver host_resolver(HostPortPair("www.gmail.com", 443));
10871  HttpNetworkSession::Params params =
10872      SpdySessionDependencies::CreateSessionParams(&session_deps_);
10873  params.host_resolver = &host_resolver;
10874  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10875  SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
10876  pool_peer.DisableDomainAuthenticationVerification();
10877
10878  SSLSocketDataProvider ssl(ASYNC, OK);
10879  ssl.SetNextProto(GetParam());
10880  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10881
10882  scoped_ptr<SpdyFrame> host1_req(
10883      spdy_util_.ConstructSpdyGet("https://www.google.com", false, 1, LOWEST));
10884  scoped_ptr<SpdyFrame> host2_req(
10885      spdy_util_.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST));
10886  MockWrite spdy_writes[] = {
10887    CreateMockWrite(*host1_req, 1),
10888    CreateMockWrite(*host2_req, 4),
10889  };
10890  scoped_ptr<SpdyFrame> host1_resp(
10891      spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
10892  scoped_ptr<SpdyFrame> host1_resp_body(
10893      spdy_util_.ConstructSpdyBodyFrame(1, true));
10894  scoped_ptr<SpdyFrame> host2_resp(
10895      spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
10896  scoped_ptr<SpdyFrame> host2_resp_body(
10897      spdy_util_.ConstructSpdyBodyFrame(3, true));
10898  MockRead spdy_reads[] = {
10899    CreateMockRead(*host1_resp, 2),
10900    CreateMockRead(*host1_resp_body, 3),
10901    CreateMockRead(*host2_resp, 5),
10902    CreateMockRead(*host2_resp_body, 6),
10903    MockRead(ASYNC, 0, 7),
10904  };
10905
10906  IPAddressNumber ip;
10907  ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip));
10908  IPEndPoint peer_addr = IPEndPoint(ip, 443);
10909  MockConnect connect(ASYNC, OK, peer_addr);
10910  OrderedSocketData spdy_data(
10911      connect,
10912      spdy_reads, arraysize(spdy_reads),
10913      spdy_writes, arraysize(spdy_writes));
10914  session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
10915
10916  TestCompletionCallback callback;
10917  HttpRequestInfo request1;
10918  request1.method = "GET";
10919  request1.url = GURL("https://www.google.com/");
10920  request1.load_flags = 0;
10921  HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
10922
10923  int rv = trans1.Start(&request1, callback.callback(), BoundNetLog());
10924  EXPECT_EQ(ERR_IO_PENDING, rv);
10925  EXPECT_EQ(OK, callback.WaitForResult());
10926
10927  const HttpResponseInfo* response = trans1.GetResponseInfo();
10928  ASSERT_TRUE(response != NULL);
10929  ASSERT_TRUE(response->headers.get() != NULL);
10930  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10931
10932  std::string response_data;
10933  ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
10934  EXPECT_EQ("hello!", response_data);
10935
10936  // Preload cache entries into HostCache.
10937  HostResolver::RequestInfo resolve_info(HostPortPair("www.gmail.com", 443));
10938  AddressList ignored;
10939  rv = host_resolver.Resolve(resolve_info,
10940                             DEFAULT_PRIORITY,
10941                             &ignored,
10942                             callback.callback(),
10943                             NULL,
10944                             BoundNetLog());
10945  EXPECT_EQ(ERR_IO_PENDING, rv);
10946  rv = callback.WaitForResult();
10947  EXPECT_EQ(OK, rv);
10948
10949  HttpRequestInfo request2;
10950  request2.method = "GET";
10951  request2.url = GURL("https://www.gmail.com/");
10952  request2.load_flags = 0;
10953  HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
10954
10955  rv = trans2.Start(&request2, callback.callback(), BoundNetLog());
10956  EXPECT_EQ(ERR_IO_PENDING, rv);
10957  EXPECT_EQ(OK, callback.WaitForResult());
10958
10959  response = trans2.GetResponseInfo();
10960  ASSERT_TRUE(response != NULL);
10961  ASSERT_TRUE(response->headers.get() != NULL);
10962  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10963  EXPECT_TRUE(response->was_fetched_via_spdy);
10964  EXPECT_TRUE(response->was_npn_negotiated);
10965  ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
10966  EXPECT_EQ("hello!", response_data);
10967}
10968#undef MAYBE_UseIPConnectionPoolingWithHostCacheExpiration
10969
10970TEST_P(HttpNetworkTransactionTest, ReadPipelineEvictionFallback) {
10971  MockRead data_reads1[] = {
10972    MockRead(SYNCHRONOUS, ERR_PIPELINE_EVICTION),
10973  };
10974  MockRead data_reads2[] = {
10975    MockRead("HTTP/1.0 200 OK\r\n\r\n"),
10976    MockRead("hello world"),
10977    MockRead(SYNCHRONOUS, OK),
10978  };
10979  StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), NULL, 0);
10980  StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), NULL, 0);
10981  StaticSocketDataProvider* data[] = { &data1, &data2 };
10982
10983  SimpleGetHelperResult out = SimpleGetHelperForData(data, arraysize(data));
10984
10985  EXPECT_EQ(OK, out.rv);
10986  EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
10987  EXPECT_EQ("hello world", out.response_data);
10988}
10989
10990TEST_P(HttpNetworkTransactionTest, SendPipelineEvictionFallback) {
10991  MockWrite data_writes1[] = {
10992    MockWrite(SYNCHRONOUS, ERR_PIPELINE_EVICTION),
10993  };
10994  MockWrite data_writes2[] = {
10995    MockWrite("GET / HTTP/1.1\r\n"
10996              "Host: www.google.com\r\n"
10997              "Connection: keep-alive\r\n\r\n"),
10998  };
10999  MockRead data_reads2[] = {
11000    MockRead("HTTP/1.0 200 OK\r\n\r\n"),
11001    MockRead("hello world"),
11002    MockRead(SYNCHRONOUS, OK),
11003  };
11004  StaticSocketDataProvider data1(NULL, 0,
11005                                 data_writes1, arraysize(data_writes1));
11006  StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
11007                                 data_writes2, arraysize(data_writes2));
11008  StaticSocketDataProvider* data[] = { &data1, &data2 };
11009
11010  SimpleGetHelperResult out = SimpleGetHelperForData(data, arraysize(data));
11011
11012  EXPECT_EQ(OK, out.rv);
11013  EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
11014  EXPECT_EQ("hello world", out.response_data);
11015}
11016
11017TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttp) {
11018  const std::string https_url = "https://www.google.com/";
11019  const std::string http_url = "http://www.google.com:443/";
11020
11021  // SPDY GET for HTTPS URL
11022  scoped_ptr<SpdyFrame> req1(
11023      spdy_util_.ConstructSpdyGet(https_url.c_str(), false, 1, LOWEST));
11024
11025  MockWrite writes1[] = {
11026    CreateMockWrite(*req1, 0),
11027  };
11028
11029  scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11030  scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
11031  MockRead reads1[] = {
11032    CreateMockRead(*resp1, 1),
11033    CreateMockRead(*body1, 2),
11034    MockRead(ASYNC, ERR_IO_PENDING, 3)
11035  };
11036
11037  DelayedSocketData data1(
11038      1, reads1, arraysize(reads1),
11039      writes1, arraysize(writes1));
11040  MockConnect connect_data1(ASYNC, OK);
11041  data1.set_connect_data(connect_data1);
11042
11043  // HTTP GET for the HTTP URL
11044  MockWrite writes2[] = {
11045    MockWrite(ASYNC, 4,
11046              "GET / HTTP/1.1\r\n"
11047              "Host: www.google.com:443\r\n"
11048              "Connection: keep-alive\r\n\r\n"),
11049  };
11050
11051  MockRead reads2[] = {
11052    MockRead(ASYNC, 5, "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
11053    MockRead(ASYNC, 6, "hello"),
11054    MockRead(ASYNC, 7, OK),
11055  };
11056
11057  DelayedSocketData data2(
11058      1, reads2, arraysize(reads2),
11059      writes2, arraysize(writes2));
11060
11061  SSLSocketDataProvider ssl(ASYNC, OK);
11062  ssl.SetNextProto(GetParam());
11063  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11064  session_deps_.socket_factory->AddSocketDataProvider(&data1);
11065  session_deps_.socket_factory->AddSocketDataProvider(&data2);
11066
11067  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11068
11069  // Start the first transaction to set up the SpdySession
11070  HttpRequestInfo request1;
11071  request1.method = "GET";
11072  request1.url = GURL(https_url);
11073  request1.load_flags = 0;
11074  HttpNetworkTransaction trans1(LOWEST, session.get());
11075  TestCompletionCallback callback1;
11076  EXPECT_EQ(ERR_IO_PENDING,
11077            trans1.Start(&request1, callback1.callback(), BoundNetLog()));
11078  base::MessageLoop::current()->RunUntilIdle();
11079
11080  EXPECT_EQ(OK, callback1.WaitForResult());
11081  EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
11082
11083  // Now, start the HTTP request
11084  HttpRequestInfo request2;
11085  request2.method = "GET";
11086  request2.url = GURL(http_url);
11087  request2.load_flags = 0;
11088  HttpNetworkTransaction trans2(MEDIUM, session.get());
11089  TestCompletionCallback callback2;
11090  EXPECT_EQ(ERR_IO_PENDING,
11091            trans2.Start(&request2, callback2.callback(), BoundNetLog()));
11092  base::MessageLoop::current()->RunUntilIdle();
11093
11094  EXPECT_EQ(OK, callback2.WaitForResult());
11095  EXPECT_FALSE(trans2.GetResponseInfo()->was_fetched_via_spdy);
11096}
11097
11098TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttpOverTunnel) {
11099  const std::string https_url = "https://www.google.com/";
11100  const std::string http_url = "http://www.google.com:443/";
11101
11102  // SPDY GET for HTTPS URL (through CONNECT tunnel)
11103  scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(NULL, 0, 1,
11104                                                                LOWEST));
11105  scoped_ptr<SpdyFrame> req1(
11106      spdy_util_.ConstructSpdyGet(https_url.c_str(), false, 1, LOWEST));
11107
11108  // SPDY GET for HTTP URL (through the proxy, but not the tunnel)
11109  scoped_ptr<SpdyFrame> wrapped_req1(
11110      spdy_util_.ConstructWrappedSpdyFrame(req1, 1));
11111  const char* const headers[] = {
11112    spdy_util_.GetMethodKey(), "GET",
11113    spdy_util_.GetPathKey(), spdy_util_.is_spdy2() ? http_url.c_str() : "/",
11114    spdy_util_.GetHostKey(),  "www.google.com:443",
11115    spdy_util_.GetSchemeKey(), "http",
11116    spdy_util_.GetVersionKey(), "HTTP/1.1"
11117  };
11118  scoped_ptr<SpdyFrame> req2(spdy_util_.ConstructSpdyControlFrame(
11119      NULL, 0, false, 3, MEDIUM, SYN_STREAM, CONTROL_FLAG_FIN,
11120      headers, arraysize(headers), 0));
11121
11122  MockWrite writes1[] = {
11123    CreateMockWrite(*connect, 0),
11124    CreateMockWrite(*wrapped_req1, 2),
11125    CreateMockWrite(*req2, 5),
11126  };
11127
11128  scoped_ptr<SpdyFrame> conn_resp(
11129      spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11130  scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11131  scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
11132  scoped_ptr<SpdyFrame> wrapped_resp1(
11133      spdy_util_.ConstructWrappedSpdyFrame(resp1, 1));
11134  scoped_ptr<SpdyFrame> wrapped_body1(
11135      spdy_util_.ConstructWrappedSpdyFrame(body1, 1));
11136  scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
11137  scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, true));
11138  MockRead reads1[] = {
11139    CreateMockRead(*conn_resp, 1),
11140    CreateMockRead(*wrapped_resp1, 3),
11141    CreateMockRead(*wrapped_body1, 4),
11142    CreateMockRead(*resp2, 6),
11143    CreateMockRead(*body2, 7),
11144    MockRead(ASYNC, ERR_IO_PENDING, 8)
11145  };
11146
11147  DeterministicSocketData data1(reads1, arraysize(reads1),
11148                                writes1, arraysize(writes1));
11149  MockConnect connect_data1(ASYNC, OK);
11150  data1.set_connect_data(connect_data1);
11151
11152  session_deps_.proxy_service.reset(
11153      ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
11154  CapturingNetLog log;
11155  session_deps_.net_log = &log;
11156  SSLSocketDataProvider ssl1(ASYNC, OK);  // to the proxy
11157  ssl1.SetNextProto(GetParam());
11158  session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl1);
11159  SSLSocketDataProvider ssl2(ASYNC, OK);  // to the server
11160  ssl2.SetNextProto(GetParam());
11161  session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2);
11162  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data1);
11163
11164  scoped_refptr<HttpNetworkSession> session(
11165      SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
11166
11167  // Start the first transaction to set up the SpdySession
11168  HttpRequestInfo request1;
11169  request1.method = "GET";
11170  request1.url = GURL(https_url);
11171  request1.load_flags = 0;
11172  HttpNetworkTransaction trans1(LOWEST, session.get());
11173  TestCompletionCallback callback1;
11174  EXPECT_EQ(ERR_IO_PENDING,
11175            trans1.Start(&request1, callback1.callback(), BoundNetLog()));
11176  base::MessageLoop::current()->RunUntilIdle();
11177  data1.RunFor(4);
11178
11179  EXPECT_EQ(OK, callback1.WaitForResult());
11180  EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
11181
11182  LoadTimingInfo load_timing_info1;
11183  EXPECT_TRUE(trans1.GetLoadTimingInfo(&load_timing_info1));
11184  TestLoadTimingNotReusedWithPac(load_timing_info1,
11185                                 CONNECT_TIMING_HAS_SSL_TIMES);
11186
11187  // Now, start the HTTP request
11188  HttpRequestInfo request2;
11189  request2.method = "GET";
11190  request2.url = GURL(http_url);
11191  request2.load_flags = 0;
11192  HttpNetworkTransaction trans2(MEDIUM, session.get());
11193  TestCompletionCallback callback2;
11194  EXPECT_EQ(ERR_IO_PENDING,
11195            trans2.Start(&request2, callback2.callback(), BoundNetLog()));
11196  base::MessageLoop::current()->RunUntilIdle();
11197  data1.RunFor(3);
11198
11199  EXPECT_EQ(OK, callback2.WaitForResult());
11200  EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
11201
11202  LoadTimingInfo load_timing_info2;
11203  EXPECT_TRUE(trans2.GetLoadTimingInfo(&load_timing_info2));
11204  // The established SPDY sessions is considered reused by the HTTP request.
11205  TestLoadTimingReusedWithPac(load_timing_info2);
11206  // HTTP requests over a SPDY session should have a different connection
11207  // socket_log_id than requests over a tunnel.
11208  EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
11209}
11210
11211TEST_P(HttpNetworkTransactionTest, UseSpdySessionForHttpWhenForced) {
11212  HttpStreamFactory::set_force_spdy_always(true);
11213  const std::string https_url = "https://www.google.com/";
11214  const std::string http_url = "http://www.google.com:443/";
11215
11216  // SPDY GET for HTTPS URL
11217  scoped_ptr<SpdyFrame> req1(
11218      spdy_util_.ConstructSpdyGet(https_url.c_str(), false, 1, LOWEST));
11219  // SPDY GET for the HTTP URL
11220  scoped_ptr<SpdyFrame> req2(
11221      spdy_util_.ConstructSpdyGet(http_url.c_str(), false, 3, MEDIUM));
11222
11223  MockWrite writes[] = {
11224    CreateMockWrite(*req1, 1),
11225    CreateMockWrite(*req2, 4),
11226  };
11227
11228  scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11229  scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
11230  scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
11231  scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, true));
11232  MockRead reads[] = {
11233    CreateMockRead(*resp1, 2),
11234    CreateMockRead(*body1, 3),
11235    CreateMockRead(*resp2, 5),
11236    CreateMockRead(*body2, 6),
11237    MockRead(ASYNC, ERR_IO_PENDING, 7)
11238  };
11239
11240  OrderedSocketData data(reads, arraysize(reads),
11241                         writes, arraysize(writes));
11242
11243  SSLSocketDataProvider ssl(ASYNC, OK);
11244  ssl.SetNextProto(GetParam());
11245  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11246  session_deps_.socket_factory->AddSocketDataProvider(&data);
11247
11248  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11249
11250  // Start the first transaction to set up the SpdySession
11251  HttpRequestInfo request1;
11252  request1.method = "GET";
11253  request1.url = GURL(https_url);
11254  request1.load_flags = 0;
11255  HttpNetworkTransaction trans1(LOWEST, session.get());
11256  TestCompletionCallback callback1;
11257  EXPECT_EQ(ERR_IO_PENDING,
11258            trans1.Start(&request1, callback1.callback(), BoundNetLog()));
11259  base::MessageLoop::current()->RunUntilIdle();
11260
11261  EXPECT_EQ(OK, callback1.WaitForResult());
11262  EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
11263
11264  // Now, start the HTTP request
11265  HttpRequestInfo request2;
11266  request2.method = "GET";
11267  request2.url = GURL(http_url);
11268  request2.load_flags = 0;
11269  HttpNetworkTransaction trans2(MEDIUM, session.get());
11270  TestCompletionCallback callback2;
11271  EXPECT_EQ(ERR_IO_PENDING,
11272            trans2.Start(&request2, callback2.callback(), BoundNetLog()));
11273  base::MessageLoop::current()->RunUntilIdle();
11274
11275  EXPECT_EQ(OK, callback2.WaitForResult());
11276  EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
11277}
11278
11279// Test that in the case where we have a SPDY session to a SPDY proxy
11280// that we do not pool other origins that resolve to the same IP when
11281// the certificate does not match the new origin.
11282// http://crbug.com/134690
11283TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionIfCertDoesNotMatch) {
11284  const std::string url1 = "http://www.google.com/";
11285  const std::string url2 = "https://mail.google.com/";
11286  const std::string ip_addr = "1.2.3.4";
11287
11288  // SPDY GET for HTTP URL (through SPDY proxy)
11289  scoped_ptr<SpdyHeaderBlock> headers(
11290      spdy_util_.ConstructGetHeaderBlockForProxy("http://www.google.com/"));
11291  scoped_ptr<SpdyFrame> req1(spdy_util_.ConstructSpdyControlFrame(
11292      headers.Pass(), false, 1, LOWEST, SYN_STREAM, CONTROL_FLAG_FIN, 0));
11293
11294  MockWrite writes1[] = {
11295    CreateMockWrite(*req1, 0),
11296  };
11297
11298  scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11299  scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
11300  MockRead reads1[] = {
11301    CreateMockRead(*resp1, 1),
11302    CreateMockRead(*body1, 2),
11303    MockRead(ASYNC, OK, 3) // EOF
11304  };
11305
11306  scoped_ptr<DeterministicSocketData> data1(
11307      new DeterministicSocketData(reads1, arraysize(reads1),
11308                                  writes1, arraysize(writes1)));
11309  IPAddressNumber ip;
11310  ASSERT_TRUE(ParseIPLiteralToNumber(ip_addr, &ip));
11311  IPEndPoint peer_addr = IPEndPoint(ip, 443);
11312  MockConnect connect_data1(ASYNC, OK, peer_addr);
11313  data1->set_connect_data(connect_data1);
11314
11315  // SPDY GET for HTTPS URL (direct)
11316  scoped_ptr<SpdyFrame> req2(
11317      spdy_util_.ConstructSpdyGet(url2.c_str(), false, 1, MEDIUM));
11318
11319  MockWrite writes2[] = {
11320    CreateMockWrite(*req2, 0),
11321  };
11322
11323  scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11324  scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
11325  MockRead reads2[] = {
11326    CreateMockRead(*resp2, 1),
11327    CreateMockRead(*body2, 2),
11328    MockRead(ASYNC, OK, 3) // EOF
11329  };
11330
11331  scoped_ptr<DeterministicSocketData> data2(
11332      new DeterministicSocketData(reads2, arraysize(reads2),
11333                                  writes2, arraysize(writes2)));
11334  MockConnect connect_data2(ASYNC, OK);
11335  data2->set_connect_data(connect_data2);
11336
11337  // Set up a proxy config that sends HTTP requests to a proxy, and
11338  // all others direct.
11339  ProxyConfig proxy_config;
11340  proxy_config.proxy_rules().ParseFromString("http=https://proxy:443");
11341  CapturingProxyResolver* capturing_proxy_resolver =
11342      new CapturingProxyResolver();
11343  session_deps_.proxy_service.reset(new ProxyService(
11344      new ProxyConfigServiceFixed(proxy_config), capturing_proxy_resolver,
11345      NULL));
11346
11347  // Load a valid cert.  Note, that this does not need to
11348  // be valid for proxy because the MockSSLClientSocket does
11349  // not actually verify it.  But SpdySession will use this
11350  // to see if it is valid for the new origin
11351  base::FilePath certs_dir = GetTestCertsDirectory();
11352  scoped_refptr<X509Certificate> server_cert(
11353      ImportCertFromFile(certs_dir, "ok_cert.pem"));
11354  ASSERT_NE(static_cast<X509Certificate*>(NULL), server_cert);
11355
11356  SSLSocketDataProvider ssl1(ASYNC, OK);  // to the proxy
11357  ssl1.SetNextProto(GetParam());
11358  ssl1.cert = server_cert;
11359  session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl1);
11360  session_deps_.deterministic_socket_factory->AddSocketDataProvider(
11361      data1.get());
11362
11363  SSLSocketDataProvider ssl2(ASYNC, OK);  // to the server
11364  ssl2.SetNextProto(GetParam());
11365  session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2);
11366  session_deps_.deterministic_socket_factory->AddSocketDataProvider(
11367      data2.get());
11368
11369  session_deps_.host_resolver.reset(new MockCachingHostResolver());
11370  session_deps_.host_resolver->rules()->AddRule("mail.google.com", ip_addr);
11371  session_deps_.host_resolver->rules()->AddRule("proxy", ip_addr);
11372
11373  scoped_refptr<HttpNetworkSession> session(
11374      SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
11375
11376  // Start the first transaction to set up the SpdySession
11377  HttpRequestInfo request1;
11378  request1.method = "GET";
11379  request1.url = GURL(url1);
11380  request1.load_flags = 0;
11381  HttpNetworkTransaction trans1(LOWEST, session.get());
11382  TestCompletionCallback callback1;
11383  ASSERT_EQ(ERR_IO_PENDING,
11384            trans1.Start(&request1, callback1.callback(), BoundNetLog()));
11385  data1->RunFor(3);
11386
11387  ASSERT_TRUE(callback1.have_result());
11388  EXPECT_EQ(OK, callback1.WaitForResult());
11389  EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
11390
11391  // Now, start the HTTP request
11392  HttpRequestInfo request2;
11393  request2.method = "GET";
11394  request2.url = GURL(url2);
11395  request2.load_flags = 0;
11396  HttpNetworkTransaction trans2(MEDIUM, session.get());
11397  TestCompletionCallback callback2;
11398  EXPECT_EQ(ERR_IO_PENDING,
11399            trans2.Start(&request2, callback2.callback(), BoundNetLog()));
11400  base::MessageLoop::current()->RunUntilIdle();
11401  data2->RunFor(3);
11402
11403  ASSERT_TRUE(callback2.have_result());
11404  EXPECT_EQ(OK, callback2.WaitForResult());
11405  EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
11406}
11407
11408// Test to verify that a failed socket read (due to an ERR_CONNECTION_CLOSED
11409// error) in SPDY session, removes the socket from pool and closes the SPDY
11410// session. Verify that new url's from the same HttpNetworkSession (and a new
11411// SpdySession) do work. http://crbug.com/224701
11412TEST_P(HttpNetworkTransactionTest, ErrorSocketNotConnected) {
11413  const std::string https_url = "https://www.google.com/";
11414
11415  MockRead reads1[] = {
11416    MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED, 0)
11417  };
11418
11419  scoped_ptr<DeterministicSocketData> data1(
11420      new DeterministicSocketData(reads1, arraysize(reads1), NULL, 0));
11421  data1->SetStop(1);
11422
11423  scoped_ptr<SpdyFrame> req2(
11424      spdy_util_.ConstructSpdyGet(https_url.c_str(), false, 1, MEDIUM));
11425  MockWrite writes2[] = {
11426    CreateMockWrite(*req2, 0),
11427  };
11428
11429  scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11430  scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
11431  MockRead reads2[] = {
11432    CreateMockRead(*resp2, 1),
11433    CreateMockRead(*body2, 2),
11434    MockRead(ASYNC, OK, 3)  // EOF
11435  };
11436
11437  scoped_ptr<DeterministicSocketData> data2(
11438      new DeterministicSocketData(reads2, arraysize(reads2),
11439                                  writes2, arraysize(writes2)));
11440
11441  SSLSocketDataProvider ssl1(ASYNC, OK);
11442  ssl1.SetNextProto(GetParam());
11443  session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl1);
11444  session_deps_.deterministic_socket_factory->AddSocketDataProvider(
11445      data1.get());
11446
11447  SSLSocketDataProvider ssl2(ASYNC, OK);
11448  ssl2.SetNextProto(GetParam());
11449  session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2);
11450  session_deps_.deterministic_socket_factory->AddSocketDataProvider(
11451      data2.get());
11452
11453  scoped_refptr<HttpNetworkSession> session(
11454      SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
11455
11456  // Start the first transaction to set up the SpdySession and verify that
11457  // connection was closed.
11458  HttpRequestInfo request1;
11459  request1.method = "GET";
11460  request1.url = GURL(https_url);
11461  request1.load_flags = 0;
11462  HttpNetworkTransaction trans1(MEDIUM, session.get());
11463  TestCompletionCallback callback1;
11464  EXPECT_EQ(ERR_IO_PENDING,
11465            trans1.Start(&request1, callback1.callback(), BoundNetLog()));
11466  base::MessageLoop::current()->RunUntilIdle();
11467  EXPECT_EQ(ERR_CONNECTION_CLOSED, callback1.WaitForResult());
11468
11469  // Now, start the second request and make sure it succeeds.
11470  HttpRequestInfo request2;
11471  request2.method = "GET";
11472  request2.url = GURL(https_url);
11473  request2.load_flags = 0;
11474  HttpNetworkTransaction trans2(MEDIUM, session.get());
11475  TestCompletionCallback callback2;
11476  EXPECT_EQ(ERR_IO_PENDING,
11477            trans2.Start(&request2, callback2.callback(), BoundNetLog()));
11478  base::MessageLoop::current()->RunUntilIdle();
11479  data2->RunFor(3);
11480
11481  ASSERT_TRUE(callback2.have_result());
11482  EXPECT_EQ(OK, callback2.WaitForResult());
11483  EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
11484}
11485
11486TEST_P(HttpNetworkTransactionTest, CloseIdleSpdySessionToOpenNewOne) {
11487  HttpStreamFactory::SetNextProtos(SpdyNextProtos());
11488  ClientSocketPoolManager::set_max_sockets_per_group(
11489      HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
11490  ClientSocketPoolManager::set_max_sockets_per_pool(
11491      HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
11492
11493  // Use two different hosts with different IPs so they don't get pooled.
11494  session_deps_.host_resolver->rules()->AddRule("www.a.com", "10.0.0.1");
11495  session_deps_.host_resolver->rules()->AddRule("www.b.com", "10.0.0.2");
11496  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11497
11498  SSLSocketDataProvider ssl1(ASYNC, OK);
11499  ssl1.SetNextProto(GetParam());
11500  SSLSocketDataProvider ssl2(ASYNC, OK);
11501  ssl2.SetNextProto(GetParam());
11502  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
11503  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
11504
11505  scoped_ptr<SpdyFrame> host1_req(spdy_util_.ConstructSpdyGet(
11506      "https://www.a.com", false, 1, DEFAULT_PRIORITY));
11507  MockWrite spdy1_writes[] = {
11508    CreateMockWrite(*host1_req, 1),
11509  };
11510  scoped_ptr<SpdyFrame> host1_resp(
11511      spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11512  scoped_ptr<SpdyFrame> host1_resp_body(
11513      spdy_util_.ConstructSpdyBodyFrame(1, true));
11514  MockRead spdy1_reads[] = {
11515    CreateMockRead(*host1_resp, 2),
11516    CreateMockRead(*host1_resp_body, 3),
11517    MockRead(ASYNC, ERR_IO_PENDING, 4),
11518  };
11519
11520  scoped_ptr<OrderedSocketData> spdy1_data(
11521      new OrderedSocketData(
11522          spdy1_reads, arraysize(spdy1_reads),
11523          spdy1_writes, arraysize(spdy1_writes)));
11524  session_deps_.socket_factory->AddSocketDataProvider(spdy1_data.get());
11525
11526  scoped_ptr<SpdyFrame> host2_req(spdy_util_.ConstructSpdyGet(
11527      "https://www.b.com", false, 1, DEFAULT_PRIORITY));
11528  MockWrite spdy2_writes[] = {
11529    CreateMockWrite(*host2_req, 1),
11530  };
11531  scoped_ptr<SpdyFrame> host2_resp(
11532      spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11533  scoped_ptr<SpdyFrame> host2_resp_body(
11534      spdy_util_.ConstructSpdyBodyFrame(1, true));
11535  MockRead spdy2_reads[] = {
11536    CreateMockRead(*host2_resp, 2),
11537    CreateMockRead(*host2_resp_body, 3),
11538    MockRead(ASYNC, ERR_IO_PENDING, 4),
11539  };
11540
11541  scoped_ptr<OrderedSocketData> spdy2_data(
11542      new OrderedSocketData(
11543          spdy2_reads, arraysize(spdy2_reads),
11544          spdy2_writes, arraysize(spdy2_writes)));
11545  session_deps_.socket_factory->AddSocketDataProvider(spdy2_data.get());
11546
11547  MockWrite http_write[] = {
11548    MockWrite("GET / HTTP/1.1\r\n"
11549              "Host: www.a.com\r\n"
11550              "Connection: keep-alive\r\n\r\n"),
11551  };
11552
11553  MockRead http_read[] = {
11554    MockRead("HTTP/1.1 200 OK\r\n"),
11555    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11556    MockRead("Content-Length: 6\r\n\r\n"),
11557    MockRead("hello!"),
11558  };
11559  StaticSocketDataProvider http_data(http_read, arraysize(http_read),
11560                                     http_write, arraysize(http_write));
11561  session_deps_.socket_factory->AddSocketDataProvider(&http_data);
11562
11563  HostPortPair host_port_pair_a("www.a.com", 443);
11564  SpdySessionKey spdy_session_key_a(
11565      host_port_pair_a, ProxyServer::Direct(), kPrivacyModeDisabled);
11566  EXPECT_FALSE(
11567      HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
11568
11569  TestCompletionCallback callback;
11570  HttpRequestInfo request1;
11571  request1.method = "GET";
11572  request1.url = GURL("https://www.a.com/");
11573  request1.load_flags = 0;
11574  scoped_ptr<HttpNetworkTransaction> trans(
11575      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
11576
11577  int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
11578  EXPECT_EQ(ERR_IO_PENDING, rv);
11579  EXPECT_EQ(OK, callback.WaitForResult());
11580
11581  const HttpResponseInfo* response = trans->GetResponseInfo();
11582  ASSERT_TRUE(response != NULL);
11583  ASSERT_TRUE(response->headers.get() != NULL);
11584  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11585  EXPECT_TRUE(response->was_fetched_via_spdy);
11586  EXPECT_TRUE(response->was_npn_negotiated);
11587
11588  std::string response_data;
11589  ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
11590  EXPECT_EQ("hello!", response_data);
11591  trans.reset();
11592  EXPECT_TRUE(
11593      HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
11594
11595  HostPortPair host_port_pair_b("www.b.com", 443);
11596  SpdySessionKey spdy_session_key_b(
11597      host_port_pair_b, ProxyServer::Direct(), kPrivacyModeDisabled);
11598  EXPECT_FALSE(
11599      HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
11600  HttpRequestInfo request2;
11601  request2.method = "GET";
11602  request2.url = GURL("https://www.b.com/");
11603  request2.load_flags = 0;
11604  trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
11605
11606  rv = trans->Start(&request2, callback.callback(), BoundNetLog());
11607  EXPECT_EQ(ERR_IO_PENDING, rv);
11608  EXPECT_EQ(OK, callback.WaitForResult());
11609
11610  response = trans->GetResponseInfo();
11611  ASSERT_TRUE(response != NULL);
11612  ASSERT_TRUE(response->headers.get() != NULL);
11613  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11614  EXPECT_TRUE(response->was_fetched_via_spdy);
11615  EXPECT_TRUE(response->was_npn_negotiated);
11616  ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
11617  EXPECT_EQ("hello!", response_data);
11618  EXPECT_FALSE(
11619      HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
11620  EXPECT_TRUE(
11621      HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
11622
11623  HostPortPair host_port_pair_a1("www.a.com", 80);
11624  SpdySessionKey spdy_session_key_a1(
11625      host_port_pair_a1, ProxyServer::Direct(), kPrivacyModeDisabled);
11626  EXPECT_FALSE(
11627      HasSpdySession(session->spdy_session_pool(), spdy_session_key_a1));
11628  HttpRequestInfo request3;
11629  request3.method = "GET";
11630  request3.url = GURL("http://www.a.com/");
11631  request3.load_flags = 0;
11632  trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
11633
11634  rv = trans->Start(&request3, callback.callback(), BoundNetLog());
11635  EXPECT_EQ(ERR_IO_PENDING, rv);
11636  EXPECT_EQ(OK, callback.WaitForResult());
11637
11638  response = trans->GetResponseInfo();
11639  ASSERT_TRUE(response != NULL);
11640  ASSERT_TRUE(response->headers.get() != NULL);
11641  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11642  EXPECT_FALSE(response->was_fetched_via_spdy);
11643  EXPECT_FALSE(response->was_npn_negotiated);
11644  ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
11645  EXPECT_EQ("hello!", response_data);
11646  EXPECT_FALSE(
11647      HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
11648  EXPECT_FALSE(
11649      HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
11650}
11651
11652TEST_P(HttpNetworkTransactionTest, HttpSyncConnectError) {
11653  HttpRequestInfo request;
11654  request.method = "GET";
11655  request.url = GURL("http://www.google.com/");
11656  request.load_flags = 0;
11657
11658  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11659  scoped_ptr<HttpTransaction> trans(
11660      new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
11661
11662  MockConnect mock_connect(SYNCHRONOUS, ERR_CONNECTION_REFUSED);
11663  StaticSocketDataProvider data;
11664  data.set_connect_data(mock_connect);
11665  session_deps_.socket_factory->AddSocketDataProvider(&data);
11666
11667  TestCompletionCallback callback;
11668
11669  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
11670  EXPECT_EQ(ERR_IO_PENDING, rv);
11671
11672  rv = callback.WaitForResult();
11673  EXPECT_EQ(ERR_CONNECTION_REFUSED, rv);
11674
11675  EXPECT_EQ(NULL, trans->GetResponseInfo());
11676
11677  // We don't care whether this succeeds or fails, but it shouldn't crash.
11678  HttpRequestHeaders request_headers;
11679  trans->GetFullRequestHeaders(&request_headers);
11680}
11681
11682TEST_P(HttpNetworkTransactionTest, HttpAsyncConnectError) {
11683  HttpRequestInfo request;
11684  request.method = "GET";
11685  request.url = GURL("http://www.google.com/");
11686  request.load_flags = 0;
11687
11688  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11689  scoped_ptr<HttpTransaction> trans(
11690      new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
11691
11692  MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
11693  StaticSocketDataProvider data;
11694  data.set_connect_data(mock_connect);
11695  session_deps_.socket_factory->AddSocketDataProvider(&data);
11696
11697  TestCompletionCallback callback;
11698
11699  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
11700  EXPECT_EQ(ERR_IO_PENDING, rv);
11701
11702  rv = callback.WaitForResult();
11703  EXPECT_EQ(ERR_CONNECTION_REFUSED, rv);
11704
11705  EXPECT_EQ(NULL, trans->GetResponseInfo());
11706
11707  // We don't care whether this succeeds or fails, but it shouldn't crash.
11708  HttpRequestHeaders request_headers;
11709  trans->GetFullRequestHeaders(&request_headers);
11710}
11711
11712TEST_P(HttpNetworkTransactionTest, HttpSyncWriteError) {
11713  HttpRequestInfo request;
11714  request.method = "GET";
11715  request.url = GURL("http://www.google.com/");
11716  request.load_flags = 0;
11717
11718  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11719  scoped_ptr<HttpTransaction> trans(
11720      new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
11721
11722  MockWrite data_writes[] = {
11723    MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
11724  };
11725  MockRead data_reads[] = {
11726    MockRead(SYNCHRONOUS, ERR_UNEXPECTED),  // Should not be reached.
11727  };
11728
11729  StaticSocketDataProvider data(data_reads, arraysize(data_reads),
11730                                data_writes, arraysize(data_writes));
11731  session_deps_.socket_factory->AddSocketDataProvider(&data);
11732
11733  TestCompletionCallback callback;
11734
11735  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
11736  EXPECT_EQ(ERR_IO_PENDING, rv);
11737
11738  rv = callback.WaitForResult();
11739  EXPECT_EQ(ERR_CONNECTION_RESET, rv);
11740
11741  EXPECT_EQ(NULL, trans->GetResponseInfo());
11742
11743  HttpRequestHeaders request_headers;
11744  EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
11745  EXPECT_TRUE(request_headers.HasHeader("Host"));
11746}
11747
11748TEST_P(HttpNetworkTransactionTest, HttpAsyncWriteError) {
11749  HttpRequestInfo request;
11750  request.method = "GET";
11751  request.url = GURL("http://www.google.com/");
11752  request.load_flags = 0;
11753
11754  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11755  scoped_ptr<HttpTransaction> trans(
11756      new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
11757
11758  MockWrite data_writes[] = {
11759    MockWrite(ASYNC, ERR_CONNECTION_RESET),
11760  };
11761  MockRead data_reads[] = {
11762    MockRead(SYNCHRONOUS, ERR_UNEXPECTED),  // Should not be reached.
11763  };
11764
11765  StaticSocketDataProvider data(data_reads, arraysize(data_reads),
11766                                data_writes, arraysize(data_writes));
11767  session_deps_.socket_factory->AddSocketDataProvider(&data);
11768
11769  TestCompletionCallback callback;
11770
11771  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
11772  EXPECT_EQ(ERR_IO_PENDING, rv);
11773
11774  rv = callback.WaitForResult();
11775  EXPECT_EQ(ERR_CONNECTION_RESET, rv);
11776
11777  EXPECT_EQ(NULL, trans->GetResponseInfo());
11778
11779  HttpRequestHeaders request_headers;
11780  EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
11781  EXPECT_TRUE(request_headers.HasHeader("Host"));
11782}
11783
11784TEST_P(HttpNetworkTransactionTest, HttpSyncReadError) {
11785  HttpRequestInfo request;
11786  request.method = "GET";
11787  request.url = GURL("http://www.google.com/");
11788  request.load_flags = 0;
11789
11790  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11791  scoped_ptr<HttpTransaction> trans(
11792      new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
11793
11794  MockWrite data_writes[] = {
11795    MockWrite("GET / HTTP/1.1\r\n"
11796              "Host: www.google.com\r\n"
11797              "Connection: keep-alive\r\n\r\n"),
11798  };
11799  MockRead data_reads[] = {
11800    MockRead(SYNCHRONOUS, ERR_CONNECTION_RESET),
11801  };
11802
11803  StaticSocketDataProvider data(data_reads, arraysize(data_reads),
11804                                data_writes, arraysize(data_writes));
11805  session_deps_.socket_factory->AddSocketDataProvider(&data);
11806
11807  TestCompletionCallback callback;
11808
11809  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
11810  EXPECT_EQ(ERR_IO_PENDING, rv);
11811
11812  rv = callback.WaitForResult();
11813  EXPECT_EQ(ERR_CONNECTION_RESET, rv);
11814
11815  EXPECT_EQ(NULL, trans->GetResponseInfo());
11816
11817  HttpRequestHeaders request_headers;
11818  EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
11819  EXPECT_TRUE(request_headers.HasHeader("Host"));
11820}
11821
11822TEST_P(HttpNetworkTransactionTest, HttpAsyncReadError) {
11823  HttpRequestInfo request;
11824  request.method = "GET";
11825  request.url = GURL("http://www.google.com/");
11826  request.load_flags = 0;
11827
11828  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11829  scoped_ptr<HttpTransaction> trans(
11830      new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
11831
11832  MockWrite data_writes[] = {
11833    MockWrite("GET / HTTP/1.1\r\n"
11834              "Host: www.google.com\r\n"
11835              "Connection: keep-alive\r\n\r\n"),
11836  };
11837  MockRead data_reads[] = {
11838    MockRead(ASYNC, ERR_CONNECTION_RESET),
11839  };
11840
11841  StaticSocketDataProvider data(data_reads, arraysize(data_reads),
11842                                data_writes, arraysize(data_writes));
11843  session_deps_.socket_factory->AddSocketDataProvider(&data);
11844
11845  TestCompletionCallback callback;
11846
11847  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
11848  EXPECT_EQ(ERR_IO_PENDING, rv);
11849
11850  rv = callback.WaitForResult();
11851  EXPECT_EQ(ERR_CONNECTION_RESET, rv);
11852
11853  EXPECT_EQ(NULL, trans->GetResponseInfo());
11854
11855  HttpRequestHeaders request_headers;
11856  EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
11857  EXPECT_TRUE(request_headers.HasHeader("Host"));
11858}
11859
11860TEST_P(HttpNetworkTransactionTest, GetFullRequestHeadersIncludesExtraHeader) {
11861  HttpRequestInfo request;
11862  request.method = "GET";
11863  request.url = GURL("http://www.google.com/");
11864  request.load_flags = 0;
11865  request.extra_headers.SetHeader("X-Foo", "bar");
11866
11867  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11868  scoped_ptr<HttpTransaction> trans(
11869      new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
11870
11871  MockWrite data_writes[] = {
11872    MockWrite("GET / HTTP/1.1\r\n"
11873              "Host: www.google.com\r\n"
11874              "Connection: keep-alive\r\n"
11875              "X-Foo: bar\r\n\r\n"),
11876  };
11877  MockRead data_reads[] = {
11878    MockRead("HTTP/1.1 200 OK\r\n"
11879             "Content-Length: 5\r\n\r\n"
11880             "hello"),
11881    MockRead(ASYNC, ERR_UNEXPECTED),
11882  };
11883
11884  StaticSocketDataProvider data(data_reads, arraysize(data_reads),
11885                                data_writes, arraysize(data_writes));
11886  session_deps_.socket_factory->AddSocketDataProvider(&data);
11887
11888  TestCompletionCallback callback;
11889
11890  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
11891  EXPECT_EQ(ERR_IO_PENDING, rv);
11892
11893  rv = callback.WaitForResult();
11894  EXPECT_EQ(OK, rv);
11895
11896  HttpRequestHeaders request_headers;
11897  EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
11898  std::string foo;
11899  EXPECT_TRUE(request_headers.GetHeader("X-Foo", &foo));
11900  EXPECT_EQ("bar", foo);
11901}
11902
11903namespace {
11904
11905// Fake HttpStreamBase that simply records calls to SetPriority().
11906class FakeStream : public HttpStreamBase,
11907                   public base::SupportsWeakPtr<FakeStream> {
11908 public:
11909  explicit FakeStream(RequestPriority priority) : priority_(priority) {}
11910  virtual ~FakeStream() {}
11911
11912  RequestPriority priority() const { return priority_; }
11913
11914  virtual int InitializeStream(const HttpRequestInfo* request_info,
11915                               RequestPriority priority,
11916                               const BoundNetLog& net_log,
11917                               const CompletionCallback& callback) OVERRIDE {
11918    return ERR_IO_PENDING;
11919  }
11920
11921  virtual int SendRequest(const HttpRequestHeaders& request_headers,
11922                          HttpResponseInfo* response,
11923                          const CompletionCallback& callback) OVERRIDE {
11924    ADD_FAILURE();
11925    return ERR_UNEXPECTED;
11926  }
11927
11928  virtual int ReadResponseHeaders(const CompletionCallback& callback) OVERRIDE {
11929    ADD_FAILURE();
11930    return ERR_UNEXPECTED;
11931  }
11932
11933  virtual const HttpResponseInfo* GetResponseInfo() const OVERRIDE {
11934    ADD_FAILURE();
11935    return NULL;
11936  }
11937
11938  virtual int ReadResponseBody(IOBuffer* buf, int buf_len,
11939                               const CompletionCallback& callback) OVERRIDE {
11940    ADD_FAILURE();
11941    return ERR_UNEXPECTED;
11942  }
11943
11944  virtual void Close(bool not_reusable) OVERRIDE {}
11945
11946  virtual bool IsResponseBodyComplete() const OVERRIDE {
11947    ADD_FAILURE();
11948    return false;
11949  }
11950
11951  virtual bool CanFindEndOfResponse() const OVERRIDE {
11952    return false;
11953  }
11954
11955  virtual bool IsConnectionReused() const OVERRIDE {
11956    ADD_FAILURE();
11957    return false;
11958  }
11959
11960  virtual void SetConnectionReused() OVERRIDE {
11961    ADD_FAILURE();
11962  }
11963
11964  virtual bool IsConnectionReusable() const OVERRIDE {
11965    ADD_FAILURE();
11966    return false;
11967  }
11968
11969  virtual int64 GetTotalReceivedBytes() const OVERRIDE {
11970    ADD_FAILURE();
11971    return 0;
11972  }
11973
11974  virtual bool GetLoadTimingInfo(
11975      LoadTimingInfo* load_timing_info) const OVERRIDE {
11976    ADD_FAILURE();
11977    return false;
11978  }
11979
11980  virtual void GetSSLInfo(SSLInfo* ssl_info) OVERRIDE {
11981    ADD_FAILURE();
11982  }
11983
11984  virtual void GetSSLCertRequestInfo(
11985      SSLCertRequestInfo* cert_request_info) OVERRIDE {
11986    ADD_FAILURE();
11987  }
11988
11989  virtual bool IsSpdyHttpStream() const OVERRIDE {
11990    ADD_FAILURE();
11991    return false;
11992  }
11993
11994  virtual void Drain(HttpNetworkSession* session) OVERRIDE {
11995    ADD_FAILURE();
11996  }
11997
11998  virtual void SetPriority(RequestPriority priority) OVERRIDE {
11999    priority_ = priority;
12000  }
12001
12002 private:
12003  RequestPriority priority_;
12004
12005  DISALLOW_COPY_AND_ASSIGN(FakeStream);
12006};
12007
12008// Fake HttpStreamRequest that simply records calls to SetPriority()
12009// and vends FakeStreams with its current priority.
12010class FakeStreamRequest : public HttpStreamRequest,
12011                          public base::SupportsWeakPtr<FakeStreamRequest> {
12012 public:
12013  FakeStreamRequest(RequestPriority priority,
12014                    HttpStreamRequest::Delegate* delegate)
12015      : priority_(priority),
12016        delegate_(delegate),
12017        websocket_stream_create_helper_(NULL) {}
12018
12019  FakeStreamRequest(RequestPriority priority,
12020                    HttpStreamRequest::Delegate* delegate,
12021                    WebSocketHandshakeStreamBase::CreateHelper* create_helper)
12022      : priority_(priority),
12023        delegate_(delegate),
12024        websocket_stream_create_helper_(create_helper) {}
12025
12026  virtual ~FakeStreamRequest() {}
12027
12028  RequestPriority priority() const { return priority_; }
12029
12030  const WebSocketHandshakeStreamBase::CreateHelper*
12031  websocket_stream_create_helper() const {
12032    return websocket_stream_create_helper_;
12033  }
12034
12035  // Create a new FakeStream and pass it to the request's
12036  // delegate. Returns a weak pointer to the FakeStream.
12037  base::WeakPtr<FakeStream> FinishStreamRequest() {
12038    FakeStream* fake_stream = new FakeStream(priority_);
12039    // Do this before calling OnStreamReady() as OnStreamReady() may
12040    // immediately delete |fake_stream|.
12041    base::WeakPtr<FakeStream> weak_stream = fake_stream->AsWeakPtr();
12042    delegate_->OnStreamReady(SSLConfig(), ProxyInfo(), fake_stream);
12043    return weak_stream;
12044  }
12045
12046  virtual int RestartTunnelWithProxyAuth(
12047      const AuthCredentials& credentials) OVERRIDE {
12048    ADD_FAILURE();
12049    return ERR_UNEXPECTED;
12050  }
12051
12052  virtual LoadState GetLoadState() const OVERRIDE {
12053    ADD_FAILURE();
12054    return LoadState();
12055  }
12056
12057  virtual void SetPriority(RequestPriority priority) OVERRIDE {
12058    priority_ = priority;
12059  }
12060
12061  virtual bool was_npn_negotiated() const OVERRIDE {
12062    return false;
12063  }
12064
12065  virtual NextProto protocol_negotiated() const OVERRIDE {
12066    return kProtoUnknown;
12067  }
12068
12069  virtual bool using_spdy() const OVERRIDE {
12070    return false;
12071  }
12072
12073 private:
12074  RequestPriority priority_;
12075  HttpStreamRequest::Delegate* const delegate_;
12076  WebSocketHandshakeStreamBase::CreateHelper* websocket_stream_create_helper_;
12077
12078  DISALLOW_COPY_AND_ASSIGN(FakeStreamRequest);
12079};
12080
12081// Fake HttpStreamFactory that vends FakeStreamRequests.
12082class FakeStreamFactory : public HttpStreamFactory {
12083 public:
12084  FakeStreamFactory() {}
12085  virtual ~FakeStreamFactory() {}
12086
12087  // Returns a WeakPtr<> to the last HttpStreamRequest returned by
12088  // RequestStream() (which may be NULL if it was destroyed already).
12089  base::WeakPtr<FakeStreamRequest> last_stream_request() {
12090    return last_stream_request_;
12091  }
12092
12093  virtual HttpStreamRequest* RequestStream(
12094      const HttpRequestInfo& info,
12095      RequestPriority priority,
12096      const SSLConfig& server_ssl_config,
12097      const SSLConfig& proxy_ssl_config,
12098      HttpStreamRequest::Delegate* delegate,
12099      const BoundNetLog& net_log) OVERRIDE {
12100    FakeStreamRequest* fake_request = new FakeStreamRequest(priority, delegate);
12101    last_stream_request_ = fake_request->AsWeakPtr();
12102    return fake_request;
12103  }
12104
12105  virtual HttpStreamRequest* RequestWebSocketHandshakeStream(
12106      const HttpRequestInfo& info,
12107      RequestPriority priority,
12108      const SSLConfig& server_ssl_config,
12109      const SSLConfig& proxy_ssl_config,
12110      HttpStreamRequest::Delegate* delegate,
12111      WebSocketHandshakeStreamBase::CreateHelper* create_helper,
12112      const BoundNetLog& net_log) OVERRIDE {
12113    FakeStreamRequest* fake_request =
12114        new FakeStreamRequest(priority, delegate, create_helper);
12115    last_stream_request_ = fake_request->AsWeakPtr();
12116    return fake_request;
12117  }
12118
12119  virtual void PreconnectStreams(int num_streams,
12120                                 const HttpRequestInfo& info,
12121                                 RequestPriority priority,
12122                                 const SSLConfig& server_ssl_config,
12123                                 const SSLConfig& proxy_ssl_config) OVERRIDE {
12124    ADD_FAILURE();
12125  }
12126
12127  virtual base::Value* PipelineInfoToValue() const OVERRIDE {
12128    ADD_FAILURE();
12129    return NULL;
12130  }
12131
12132  virtual const HostMappingRules* GetHostMappingRules() const OVERRIDE {
12133    ADD_FAILURE();
12134    return NULL;
12135  }
12136
12137 private:
12138  base::WeakPtr<FakeStreamRequest> last_stream_request_;
12139
12140  DISALLOW_COPY_AND_ASSIGN(FakeStreamFactory);
12141};
12142
12143// TODO(yhirano): Split this class out into a net/websockets file, if it is
12144// worth doing.
12145class FakeWebSocketStreamCreateHelper :
12146      public WebSocketHandshakeStreamBase::CreateHelper {
12147 public:
12148  virtual WebSocketHandshakeStreamBase* CreateBasicStream(
12149      scoped_ptr<ClientSocketHandle> connection,
12150      bool using_proxy) OVERRIDE {
12151    NOTREACHED();
12152    return NULL;
12153  }
12154
12155  virtual WebSocketHandshakeStreamBase* CreateSpdyStream(
12156      const base::WeakPtr<SpdySession>& session,
12157      bool use_relative_url) OVERRIDE {
12158    NOTREACHED();
12159    return NULL;
12160  };
12161
12162  virtual ~FakeWebSocketStreamCreateHelper() {}
12163
12164  virtual scoped_ptr<WebSocketStream> Upgrade() {
12165    NOTREACHED();
12166    return scoped_ptr<WebSocketStream>();
12167  }
12168};
12169
12170}  // namespace
12171
12172// Make sure that HttpNetworkTransaction passes on its priority to its
12173// stream request on start.
12174TEST_P(HttpNetworkTransactionTest, SetStreamRequestPriorityOnStart) {
12175  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12176  HttpNetworkSessionPeer peer(session);
12177  FakeStreamFactory* fake_factory = new FakeStreamFactory();
12178  peer.SetHttpStreamFactory(scoped_ptr<HttpStreamFactory>(fake_factory));
12179
12180  HttpNetworkTransaction trans(LOW, session);
12181
12182  ASSERT_TRUE(fake_factory->last_stream_request() == NULL);
12183
12184  HttpRequestInfo request;
12185  TestCompletionCallback callback;
12186  EXPECT_EQ(ERR_IO_PENDING,
12187            trans.Start(&request, callback.callback(), BoundNetLog()));
12188
12189  base::WeakPtr<FakeStreamRequest> fake_request =
12190      fake_factory->last_stream_request();
12191  ASSERT_TRUE(fake_request != NULL);
12192  EXPECT_EQ(LOW, fake_request->priority());
12193}
12194
12195// Make sure that HttpNetworkTransaction passes on its priority
12196// updates to its stream request.
12197TEST_P(HttpNetworkTransactionTest, SetStreamRequestPriority) {
12198  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12199  HttpNetworkSessionPeer peer(session);
12200  FakeStreamFactory* fake_factory = new FakeStreamFactory();
12201  peer.SetHttpStreamFactory(scoped_ptr<HttpStreamFactory>(fake_factory));
12202
12203  HttpNetworkTransaction trans(LOW, session);
12204
12205  HttpRequestInfo request;
12206  TestCompletionCallback callback;
12207  EXPECT_EQ(ERR_IO_PENDING,
12208            trans.Start(&request, callback.callback(), BoundNetLog()));
12209
12210  base::WeakPtr<FakeStreamRequest> fake_request =
12211      fake_factory->last_stream_request();
12212  ASSERT_TRUE(fake_request != NULL);
12213  EXPECT_EQ(LOW, fake_request->priority());
12214
12215  trans.SetPriority(LOWEST);
12216  ASSERT_TRUE(fake_request != NULL);
12217  EXPECT_EQ(LOWEST, fake_request->priority());
12218}
12219
12220// Make sure that HttpNetworkTransaction passes on its priority
12221// updates to its stream.
12222TEST_P(HttpNetworkTransactionTest, SetStreamPriority) {
12223  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12224  HttpNetworkSessionPeer peer(session);
12225  FakeStreamFactory* fake_factory = new FakeStreamFactory();
12226  peer.SetHttpStreamFactory(scoped_ptr<HttpStreamFactory>(fake_factory));
12227
12228  HttpNetworkTransaction trans(LOW, session);
12229
12230  HttpRequestInfo request;
12231  TestCompletionCallback callback;
12232  EXPECT_EQ(ERR_IO_PENDING,
12233            trans.Start(&request, callback.callback(), BoundNetLog()));
12234
12235  base::WeakPtr<FakeStreamRequest> fake_request =
12236      fake_factory->last_stream_request();
12237  ASSERT_TRUE(fake_request != NULL);
12238  base::WeakPtr<FakeStream> fake_stream = fake_request->FinishStreamRequest();
12239  ASSERT_TRUE(fake_stream != NULL);
12240  EXPECT_EQ(LOW, fake_stream->priority());
12241
12242  trans.SetPriority(LOWEST);
12243  EXPECT_EQ(LOWEST, fake_stream->priority());
12244}
12245
12246TEST_P(HttpNetworkTransactionTest, CreateWebSocketHandshakeStream) {
12247  // The same logic needs to be tested for both ws: and wss: schemes, but this
12248  // test is already parameterised on NextProto, so it uses a loop to verify
12249  // that the different schemes work.
12250  std::string test_cases[] = {"ws://www.google.com/", "wss://www.google.com/"};
12251  for (size_t i = 0; i < arraysize(test_cases); ++i) {
12252    scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12253    HttpNetworkSessionPeer peer(session);
12254    FakeStreamFactory* fake_factory = new FakeStreamFactory();
12255    FakeWebSocketStreamCreateHelper websocket_stream_create_helper;
12256    peer.SetHttpStreamFactoryForWebSocket(
12257        scoped_ptr<HttpStreamFactory>(fake_factory));
12258
12259    HttpNetworkTransaction trans(LOW, session);
12260    trans.SetWebSocketHandshakeStreamCreateHelper(
12261        &websocket_stream_create_helper);
12262
12263    HttpRequestInfo request;
12264    TestCompletionCallback callback;
12265    request.method = "GET";
12266    request.url = GURL(test_cases[i]);
12267
12268    EXPECT_EQ(ERR_IO_PENDING,
12269              trans.Start(&request, callback.callback(), BoundNetLog()));
12270
12271    base::WeakPtr<FakeStreamRequest> fake_request =
12272        fake_factory->last_stream_request();
12273    ASSERT_TRUE(fake_request != NULL);
12274    EXPECT_EQ(&websocket_stream_create_helper,
12275              fake_request->websocket_stream_create_helper());
12276  }
12277}
12278
12279// Tests that when a used socket is returned to the SSL socket pool, it's closed
12280// if the transport socket pool is stalled on the global socket limit.
12281TEST_P(HttpNetworkTransactionTest, CloseSSLSocketOnIdleForHttpRequest) {
12282  ClientSocketPoolManager::set_max_sockets_per_group(
12283      HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
12284  ClientSocketPoolManager::set_max_sockets_per_pool(
12285      HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
12286
12287  // Set up SSL request.
12288
12289  HttpRequestInfo ssl_request;
12290  ssl_request.method = "GET";
12291  ssl_request.url = GURL("https://www.google.com/");
12292
12293  MockWrite ssl_writes[] = {
12294    MockWrite("GET / HTTP/1.1\r\n"
12295              "Host: www.google.com\r\n"
12296              "Connection: keep-alive\r\n\r\n"),
12297  };
12298  MockRead ssl_reads[] = {
12299    MockRead("HTTP/1.1 200 OK\r\n"),
12300    MockRead("Content-Length: 11\r\n\r\n"),
12301    MockRead("hello world"),
12302    MockRead(SYNCHRONOUS, OK),
12303  };
12304  StaticSocketDataProvider ssl_data(ssl_reads, arraysize(ssl_reads),
12305                                    ssl_writes, arraysize(ssl_writes));
12306  session_deps_.socket_factory->AddSocketDataProvider(&ssl_data);
12307
12308  SSLSocketDataProvider ssl(ASYNC, OK);
12309  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12310
12311  // Set up HTTP request.
12312
12313  HttpRequestInfo http_request;
12314  http_request.method = "GET";
12315  http_request.url = GURL("http://www.google.com/");
12316
12317  MockWrite http_writes[] = {
12318    MockWrite("GET / HTTP/1.1\r\n"
12319              "Host: www.google.com\r\n"
12320              "Connection: keep-alive\r\n\r\n"),
12321  };
12322  MockRead http_reads[] = {
12323    MockRead("HTTP/1.1 200 OK\r\n"),
12324    MockRead("Content-Length: 7\r\n\r\n"),
12325    MockRead("falafel"),
12326    MockRead(SYNCHRONOUS, OK),
12327  };
12328  StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
12329                                     http_writes, arraysize(http_writes));
12330  session_deps_.socket_factory->AddSocketDataProvider(&http_data);
12331
12332  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12333
12334  // Start the SSL request.
12335  TestCompletionCallback ssl_callback;
12336  scoped_ptr<HttpTransaction> ssl_trans(
12337      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12338  ASSERT_EQ(ERR_IO_PENDING,
12339            ssl_trans->Start(&ssl_request, ssl_callback.callback(),
12340            BoundNetLog()));
12341
12342  // Start the HTTP request.  Pool should stall.
12343  TestCompletionCallback http_callback;
12344  scoped_ptr<HttpTransaction> http_trans(
12345      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12346  ASSERT_EQ(ERR_IO_PENDING,
12347            http_trans->Start(&http_request, http_callback.callback(),
12348                              BoundNetLog()));
12349  EXPECT_TRUE(IsTransportSocketPoolStalled(session));
12350
12351  // Wait for response from SSL request.
12352  ASSERT_EQ(OK, ssl_callback.WaitForResult());
12353  std::string response_data;
12354  ASSERT_EQ(OK, ReadTransaction(ssl_trans.get(), &response_data));
12355  EXPECT_EQ("hello world", response_data);
12356
12357  // The SSL socket should automatically be closed, so the HTTP request can
12358  // start.
12359  EXPECT_EQ(0, GetIdleSocketCountInSSLSocketPool(session));
12360  ASSERT_FALSE(IsTransportSocketPoolStalled(session));
12361
12362  // The HTTP request can now complete.
12363  ASSERT_EQ(OK, http_callback.WaitForResult());
12364  ASSERT_EQ(OK, ReadTransaction(http_trans.get(), &response_data));
12365  EXPECT_EQ("falafel", response_data);
12366
12367  EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session));
12368}
12369
12370// Tests that when a SSL connection is established but there's no corresponding
12371// request that needs it, the new socket is closed if the transport socket pool
12372// is stalled on the global socket limit.
12373TEST_P(HttpNetworkTransactionTest, CloseSSLSocketOnIdleForHttpRequest2) {
12374  ClientSocketPoolManager::set_max_sockets_per_group(
12375      HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
12376  ClientSocketPoolManager::set_max_sockets_per_pool(
12377      HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
12378
12379  // Set up an ssl request.
12380
12381  HttpRequestInfo ssl_request;
12382  ssl_request.method = "GET";
12383  ssl_request.url = GURL("https://www.foopy.com/");
12384
12385  // No data will be sent on the SSL socket.
12386  StaticSocketDataProvider ssl_data;
12387  session_deps_.socket_factory->AddSocketDataProvider(&ssl_data);
12388
12389  SSLSocketDataProvider ssl(ASYNC, OK);
12390  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12391
12392  // Set up HTTP request.
12393
12394  HttpRequestInfo http_request;
12395  http_request.method = "GET";
12396  http_request.url = GURL("http://www.google.com/");
12397
12398  MockWrite http_writes[] = {
12399    MockWrite("GET / HTTP/1.1\r\n"
12400              "Host: www.google.com\r\n"
12401              "Connection: keep-alive\r\n\r\n"),
12402  };
12403  MockRead http_reads[] = {
12404    MockRead("HTTP/1.1 200 OK\r\n"),
12405    MockRead("Content-Length: 7\r\n\r\n"),
12406    MockRead("falafel"),
12407    MockRead(SYNCHRONOUS, OK),
12408  };
12409  StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
12410                                     http_writes, arraysize(http_writes));
12411  session_deps_.socket_factory->AddSocketDataProvider(&http_data);
12412
12413  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12414
12415  // Preconnect an SSL socket.  A preconnect is needed because connect jobs are
12416  // cancelled when a normal transaction is cancelled.
12417  net::HttpStreamFactory* http_stream_factory = session->http_stream_factory();
12418  net::SSLConfig ssl_config;
12419  session->ssl_config_service()->GetSSLConfig(&ssl_config);
12420  http_stream_factory->PreconnectStreams(1, ssl_request, DEFAULT_PRIORITY,
12421                                         ssl_config, ssl_config);
12422  EXPECT_EQ(0, GetIdleSocketCountInSSLSocketPool(session));
12423
12424  // Start the HTTP request.  Pool should stall.
12425  TestCompletionCallback http_callback;
12426  scoped_ptr<HttpTransaction> http_trans(
12427      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12428  ASSERT_EQ(ERR_IO_PENDING,
12429            http_trans->Start(&http_request, http_callback.callback(),
12430                              BoundNetLog()));
12431  EXPECT_TRUE(IsTransportSocketPoolStalled(session));
12432
12433  // The SSL connection will automatically be closed once the connection is
12434  // established, to let the HTTP request start.
12435  ASSERT_EQ(OK, http_callback.WaitForResult());
12436  std::string response_data;
12437  ASSERT_EQ(OK, ReadTransaction(http_trans.get(), &response_data));
12438  EXPECT_EQ("falafel", response_data);
12439
12440  EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session));
12441}
12442
12443}  // namespace net
12444