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/strings/string_util.h"
19#include "base/strings/utf_string_conversions.h"
20#include "base/test/test_file_util.h"
21#include "net/base/auth.h"
22#include "net/base/capturing_net_log.h"
23#include "net/base/completion_callback.h"
24#include "net/base/load_timing_info.h"
25#include "net/base/load_timing_info_test_util.h"
26#include "net/base/net_log.h"
27#include "net/base/net_log_unittest.h"
28#include "net/base/request_priority.h"
29#include "net/base/test_completion_callback.h"
30#include "net/base/test_data_directory.h"
31#include "net/base/upload_bytes_element_reader.h"
32#include "net/base/upload_data_stream.h"
33#include "net/base/upload_file_element_reader.h"
34#include "net/cert/mock_cert_verifier.h"
35#include "net/dns/host_cache.h"
36#include "net/dns/mock_host_resolver.h"
37#include "net/http/http_auth_handler_digest.h"
38#include "net/http/http_auth_handler_mock.h"
39#include "net/http/http_auth_handler_ntlm.h"
40#include "net/http/http_basic_stream.h"
41#include "net/http/http_network_session.h"
42#include "net/http/http_network_session_peer.h"
43#include "net/http/http_server_properties_impl.h"
44#include "net/http/http_stream.h"
45#include "net/http/http_stream_factory.h"
46#include "net/http/http_transaction_unittest.h"
47#include "net/proxy/proxy_config_service_fixed.h"
48#include "net/proxy/proxy_resolver.h"
49#include "net/proxy/proxy_service.h"
50#include "net/socket/client_socket_factory.h"
51#include "net/socket/client_socket_pool_manager.h"
52#include "net/socket/mock_client_socket_pool_manager.h"
53#include "net/socket/next_proto.h"
54#include "net/socket/socket_test_util.h"
55#include "net/socket/ssl_client_socket.h"
56#include "net/spdy/spdy_framer.h"
57#include "net/spdy/spdy_session.h"
58#include "net/spdy/spdy_session_pool.h"
59#include "net/spdy/spdy_test_util_common.h"
60#include "net/ssl/ssl_cert_request_info.h"
61#include "net/ssl/ssl_config_service_defaults.h"
62#include "net/ssl/ssl_info.h"
63#include "net/test/cert_test_util.h"
64#include "testing/gtest/include/gtest/gtest.h"
65#include "testing/platform_test.h"
66#include "url/gurl.h"
67
68//-----------------------------------------------------------------------------
69
70namespace {
71
72const base::string16 kBar(ASCIIToUTF16("bar"));
73const base::string16 kBar2(ASCIIToUTF16("bar2"));
74const base::string16 kBar3(ASCIIToUTF16("bar3"));
75const base::string16 kBaz(ASCIIToUTF16("baz"));
76const base::string16 kFirst(ASCIIToUTF16("first"));
77const base::string16 kFoo(ASCIIToUTF16("foo"));
78const base::string16 kFoo2(ASCIIToUTF16("foo2"));
79const base::string16 kFoo3(ASCIIToUTF16("foo3"));
80const base::string16 kFou(ASCIIToUTF16("fou"));
81const base::string16 kSecond(ASCIIToUTF16("second"));
82const base::string16 kTestingNTLM(ASCIIToUTF16("testing-ntlm"));
83const base::string16 kWrongPassword(ASCIIToUTF16("wrongpassword"));
84
85int GetIdleSocketCountInTransportSocketPool(net::HttpNetworkSession* session) {
86  return session->GetTransportSocketPool(
87      net::HttpNetworkSession::NORMAL_SOCKET_POOL)->IdleSocketCount();
88}
89
90int GetIdleSocketCountInSSLSocketPool(net::HttpNetworkSession* session) {
91  return session->GetSSLSocketPool(
92      net::HttpNetworkSession::NORMAL_SOCKET_POOL)->IdleSocketCount();
93}
94
95// Takes in a Value created from a NetLogHttpResponseParameter, and returns
96// a JSONified list of headers as a single string.  Uses single quotes instead
97// of double quotes for easier comparison.  Returns false on failure.
98bool GetHeaders(base::DictionaryValue* params, std::string* headers) {
99  if (!params)
100    return false;
101  base::ListValue* header_list;
102  if (!params->GetList("headers", &header_list))
103    return false;
104  std::string double_quote_headers;
105  base::JSONWriter::Write(header_list, &double_quote_headers);
106  ReplaceChars(double_quote_headers, "\"", "'", headers);
107  return true;
108}
109
110// Tests LoadTimingInfo in the case a socket is reused and no PAC script is
111// used.
112void TestLoadTimingReused(const net::LoadTimingInfo& load_timing_info) {
113  EXPECT_TRUE(load_timing_info.socket_reused);
114  EXPECT_NE(net::NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
115
116  EXPECT_TRUE(load_timing_info.proxy_resolve_start.is_null());
117  EXPECT_TRUE(load_timing_info.proxy_resolve_end.is_null());
118
119  net::ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
120  EXPECT_FALSE(load_timing_info.send_start.is_null());
121
122  EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
123
124  // Set at a higher level.
125  EXPECT_TRUE(load_timing_info.request_start_time.is_null());
126  EXPECT_TRUE(load_timing_info.request_start.is_null());
127  EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
128}
129
130// Tests LoadTimingInfo in the case a new socket is used and no PAC script is
131// used.
132void TestLoadTimingNotReused(const net::LoadTimingInfo& load_timing_info,
133                             int connect_timing_flags) {
134  EXPECT_FALSE(load_timing_info.socket_reused);
135  EXPECT_NE(net::NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
136
137  EXPECT_TRUE(load_timing_info.proxy_resolve_start.is_null());
138  EXPECT_TRUE(load_timing_info.proxy_resolve_end.is_null());
139
140  net::ExpectConnectTimingHasTimes(load_timing_info.connect_timing,
141                                   connect_timing_flags);
142  EXPECT_LE(load_timing_info.connect_timing.connect_end,
143            load_timing_info.send_start);
144
145  EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
146
147  // Set at a higher level.
148  EXPECT_TRUE(load_timing_info.request_start_time.is_null());
149  EXPECT_TRUE(load_timing_info.request_start.is_null());
150  EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
151}
152
153// Tests LoadTimingInfo in the case a socket is reused and a PAC script is
154// used.
155void TestLoadTimingReusedWithPac(const net::LoadTimingInfo& load_timing_info) {
156  EXPECT_TRUE(load_timing_info.socket_reused);
157  EXPECT_NE(net::NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
158
159  net::ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
160
161  EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null());
162  EXPECT_LE(load_timing_info.proxy_resolve_start,
163            load_timing_info.proxy_resolve_end);
164  EXPECT_LE(load_timing_info.proxy_resolve_end,
165            load_timing_info.send_start);
166  EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
167
168  // Set at a higher level.
169  EXPECT_TRUE(load_timing_info.request_start_time.is_null());
170  EXPECT_TRUE(load_timing_info.request_start.is_null());
171  EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
172}
173
174// Tests LoadTimingInfo in the case a new socket is used and a PAC script is
175// used.
176void TestLoadTimingNotReusedWithPac(const net::LoadTimingInfo& load_timing_info,
177                                    int connect_timing_flags) {
178  EXPECT_FALSE(load_timing_info.socket_reused);
179  EXPECT_NE(net::NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
180
181  EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null());
182  EXPECT_LE(load_timing_info.proxy_resolve_start,
183            load_timing_info.proxy_resolve_end);
184  EXPECT_LE(load_timing_info.proxy_resolve_end,
185            load_timing_info.connect_timing.connect_start);
186  net::ExpectConnectTimingHasTimes(load_timing_info.connect_timing,
187                                   connect_timing_flags);
188  EXPECT_LE(load_timing_info.connect_timing.connect_end,
189            load_timing_info.send_start);
190
191  EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
192
193  // Set at a higher level.
194  EXPECT_TRUE(load_timing_info.request_start_time.is_null());
195  EXPECT_TRUE(load_timing_info.request_start.is_null());
196  EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
197}
198
199}  // namespace
200
201namespace net {
202
203namespace {
204
205HttpNetworkSession* CreateSession(SpdySessionDependencies* session_deps) {
206  return SpdySessionDependencies::SpdyCreateSession(session_deps);
207}
208
209}  // namespace
210
211class HttpNetworkTransactionTest
212    : public PlatformTest,
213      public ::testing::WithParamInterface<NextProto> {
214 public:
215  virtual ~HttpNetworkTransactionTest() {
216    // Important to restore the per-pool limit first, since the pool limit must
217    // always be greater than group limit, and the tests reduce both limits.
218    ClientSocketPoolManager::set_max_sockets_per_pool(
219        HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_pool_sockets_);
220    ClientSocketPoolManager::set_max_sockets_per_group(
221        HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_group_sockets_);
222  }
223
224 protected:
225  HttpNetworkTransactionTest()
226      : spdy_util_(GetParam()),
227        session_deps_(GetParam()),
228        old_max_group_sockets_(ClientSocketPoolManager::max_sockets_per_group(
229            HttpNetworkSession::NORMAL_SOCKET_POOL)),
230        old_max_pool_sockets_(ClientSocketPoolManager::max_sockets_per_pool(
231            HttpNetworkSession::NORMAL_SOCKET_POOL)) {
232  }
233
234  struct SimpleGetHelperResult {
235    int rv;
236    std::string status_line;
237    std::string response_data;
238    LoadTimingInfo load_timing_info;
239  };
240
241  virtual void SetUp() {
242    NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
243    base::MessageLoop::current()->RunUntilIdle();
244  }
245
246  virtual void TearDown() {
247    NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
248    base::MessageLoop::current()->RunUntilIdle();
249    // Empty the current queue.
250    base::MessageLoop::current()->RunUntilIdle();
251    PlatformTest::TearDown();
252    NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
253    base::MessageLoop::current()->RunUntilIdle();
254    HttpStreamFactory::set_use_alternate_protocols(false);
255    HttpStreamFactory::SetNextProtos(std::vector<NextProto>());
256  }
257
258  // This is the expected return from a current server advertising SPDY.
259  std::string GetAlternateProtocolHttpHeader() {
260    return
261        std::string("Alternate-Protocol: 443:") +
262        AlternateProtocolToString(AlternateProtocolFromNextProto(GetParam())) +
263        "\r\n\r\n";
264  }
265
266  // Either |write_failure| specifies a write failure or |read_failure|
267  // specifies a read failure when using a reused socket.  In either case, the
268  // failure should cause the network transaction to resend the request, and the
269  // other argument should be NULL.
270  void KeepAliveConnectionResendRequestTest(const MockWrite* write_failure,
271                                            const MockRead* read_failure);
272
273  SimpleGetHelperResult SimpleGetHelperForData(StaticSocketDataProvider* data[],
274                                               size_t data_count) {
275    SimpleGetHelperResult out;
276
277    HttpRequestInfo request;
278    request.method = "GET";
279    request.url = GURL("http://www.google.com/");
280    request.load_flags = 0;
281
282    CapturingBoundNetLog log;
283    session_deps_.net_log = log.bound().net_log();
284    scoped_ptr<HttpTransaction> trans(
285        new HttpNetworkTransaction(DEFAULT_PRIORITY,
286                                   CreateSession(&session_deps_)));
287
288    for (size_t i = 0; i < data_count; ++i) {
289      session_deps_.socket_factory->AddSocketDataProvider(data[i]);
290    }
291
292    TestCompletionCallback callback;
293
294    EXPECT_TRUE(log.bound().IsLoggingAllEvents());
295    int rv = trans->Start(&request, callback.callback(), log.bound());
296    EXPECT_EQ(ERR_IO_PENDING, rv);
297
298    out.rv = callback.WaitForResult();
299
300    // Even in the failure cases that use this function, connections are always
301    // successfully established before the error.
302    EXPECT_TRUE(trans->GetLoadTimingInfo(&out.load_timing_info));
303    TestLoadTimingNotReused(out.load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
304
305    if (out.rv != OK)
306      return out;
307
308    const HttpResponseInfo* response = trans->GetResponseInfo();
309    // Can't use ASSERT_* inside helper functions like this, so
310    // return an error.
311    if (response == NULL || response->headers.get() == NULL) {
312      out.rv = ERR_UNEXPECTED;
313      return out;
314    }
315    out.status_line = response->headers->GetStatusLine();
316
317    EXPECT_EQ("127.0.0.1", response->socket_address.host());
318    EXPECT_EQ(80, response->socket_address.port());
319
320    rv = ReadTransaction(trans.get(), &out.response_data);
321    EXPECT_EQ(OK, rv);
322
323    net::CapturingNetLog::CapturedEntryList entries;
324    log.GetEntries(&entries);
325    size_t pos = ExpectLogContainsSomewhere(
326        entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS,
327        NetLog::PHASE_NONE);
328    ExpectLogContainsSomewhere(
329        entries, pos,
330        NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS,
331        NetLog::PHASE_NONE);
332
333    std::string line;
334    EXPECT_TRUE(entries[pos].GetStringValue("line", &line));
335    EXPECT_EQ("GET / HTTP/1.1\r\n", line);
336
337    HttpRequestHeaders request_headers;
338    EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
339    std::string value;
340    EXPECT_TRUE(request_headers.GetHeader("Host", &value));
341    EXPECT_EQ("www.google.com", value);
342    EXPECT_TRUE(request_headers.GetHeader("Connection", &value));
343    EXPECT_EQ("keep-alive", value);
344
345    std::string response_headers;
346    EXPECT_TRUE(GetHeaders(entries[pos].params.get(), &response_headers));
347    EXPECT_EQ("['Host: www.google.com','Connection: keep-alive']",
348              response_headers);
349
350    return out;
351  }
352
353  SimpleGetHelperResult SimpleGetHelper(MockRead data_reads[],
354                                        size_t reads_count) {
355    StaticSocketDataProvider reads(data_reads, reads_count, NULL, 0);
356    StaticSocketDataProvider* data[] = { &reads };
357    return SimpleGetHelperForData(data, 1);
358  }
359
360  void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
361                                             int expected_status);
362
363  void ConnectStatusHelper(const MockRead& status);
364
365  void BypassHostCacheOnRefreshHelper(int load_flags);
366
367  void CheckErrorIsPassedBack(int error, IoMode mode);
368
369  SpdyTestUtil spdy_util_;
370  SpdySessionDependencies session_deps_;
371
372  // Original socket limits.  Some tests set these.  Safest to always restore
373  // them once each test has been run.
374  int old_max_group_sockets_;
375  int old_max_pool_sockets_;
376};
377
378INSTANTIATE_TEST_CASE_P(
379    NextProto,
380    HttpNetworkTransactionTest,
381    testing::Values(kProtoSPDY2, kProtoSPDY3, kProtoSPDY31, kProtoSPDY4a2,
382                    kProtoHTTP2Draft04));
383
384namespace {
385
386// Fill |str| with a long header list that consumes >= |size| bytes.
387void FillLargeHeadersString(std::string* str, int size) {
388  const char* row =
389      "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
390  const int sizeof_row = strlen(row);
391  const int num_rows = static_cast<int>(
392      ceil(static_cast<float>(size) / sizeof_row));
393  const int sizeof_data = num_rows * sizeof_row;
394  DCHECK(sizeof_data >= size);
395  str->reserve(sizeof_data);
396
397  for (int i = 0; i < num_rows; ++i)
398    str->append(row, sizeof_row);
399}
400
401// Alternative functions that eliminate randomness and dependency on the local
402// host name so that the generated NTLM messages are reproducible.
403void MockGenerateRandom1(uint8* output, size_t n) {
404  static const uint8 bytes[] = {
405    0x55, 0x29, 0x66, 0x26, 0x6b, 0x9c, 0x73, 0x54
406  };
407  static size_t current_byte = 0;
408  for (size_t i = 0; i < n; ++i) {
409    output[i] = bytes[current_byte++];
410    current_byte %= arraysize(bytes);
411  }
412}
413
414void MockGenerateRandom2(uint8* output, size_t n) {
415  static const uint8 bytes[] = {
416    0x96, 0x79, 0x85, 0xe7, 0x49, 0x93, 0x70, 0xa1,
417    0x4e, 0xe7, 0x87, 0x45, 0x31, 0x5b, 0xd3, 0x1f
418  };
419  static size_t current_byte = 0;
420  for (size_t i = 0; i < n; ++i) {
421    output[i] = bytes[current_byte++];
422    current_byte %= arraysize(bytes);
423  }
424}
425
426std::string MockGetHostName() {
427  return "WTC-WIN7";
428}
429
430template<typename ParentPool>
431class CaptureGroupNameSocketPool : public ParentPool {
432 public:
433  CaptureGroupNameSocketPool(HostResolver* host_resolver,
434                             CertVerifier* cert_verifier);
435
436  const std::string last_group_name_received() const {
437    return last_group_name_;
438  }
439
440  virtual int RequestSocket(const std::string& group_name,
441                            const void* socket_params,
442                            RequestPriority priority,
443                            ClientSocketHandle* handle,
444                            const CompletionCallback& callback,
445                            const BoundNetLog& net_log) {
446    last_group_name_ = group_name;
447    return ERR_IO_PENDING;
448  }
449  virtual void CancelRequest(const std::string& group_name,
450                             ClientSocketHandle* handle) {}
451  virtual void ReleaseSocket(const std::string& group_name,
452                             StreamSocket* socket,
453                             int id) {}
454  virtual void CloseIdleSockets() {}
455  virtual int IdleSocketCount() const {
456    return 0;
457  }
458  virtual int IdleSocketCountInGroup(const std::string& group_name) const {
459    return 0;
460  }
461  virtual LoadState GetLoadState(const std::string& group_name,
462                                 const ClientSocketHandle* handle) const {
463    return LOAD_STATE_IDLE;
464  }
465  virtual base::TimeDelta ConnectionTimeout() const {
466    return base::TimeDelta();
467  }
468
469 private:
470  std::string last_group_name_;
471};
472
473typedef CaptureGroupNameSocketPool<TransportClientSocketPool>
474CaptureGroupNameTransportSocketPool;
475typedef CaptureGroupNameSocketPool<HttpProxyClientSocketPool>
476CaptureGroupNameHttpProxySocketPool;
477typedef CaptureGroupNameSocketPool<SOCKSClientSocketPool>
478CaptureGroupNameSOCKSSocketPool;
479typedef CaptureGroupNameSocketPool<SSLClientSocketPool>
480CaptureGroupNameSSLSocketPool;
481
482template<typename ParentPool>
483CaptureGroupNameSocketPool<ParentPool>::CaptureGroupNameSocketPool(
484    HostResolver* host_resolver,
485    CertVerifier* /* cert_verifier */)
486    : ParentPool(0, 0, NULL, host_resolver, NULL, NULL) {}
487
488template<>
489CaptureGroupNameHttpProxySocketPool::CaptureGroupNameSocketPool(
490    HostResolver* host_resolver,
491    CertVerifier* /* cert_verifier */)
492    : HttpProxyClientSocketPool(0, 0, NULL, host_resolver, NULL, NULL, NULL) {}
493
494template <>
495CaptureGroupNameSSLSocketPool::CaptureGroupNameSocketPool(
496    HostResolver* host_resolver,
497    CertVerifier* cert_verifier)
498    : SSLClientSocketPool(0,
499                          0,
500                          NULL,
501                          host_resolver,
502                          cert_verifier,
503                          NULL,
504                          NULL,
505                          std::string(),
506                          NULL,
507                          NULL,
508                          NULL,
509                          NULL,
510                          NULL,
511                          NULL) {}
512
513//-----------------------------------------------------------------------------
514
515// Helper functions for validating that AuthChallengeInfo's are correctly
516// configured for common cases.
517bool CheckBasicServerAuth(const AuthChallengeInfo* auth_challenge) {
518  if (!auth_challenge)
519    return false;
520  EXPECT_FALSE(auth_challenge->is_proxy);
521  EXPECT_EQ("www.google.com:80", auth_challenge->challenger.ToString());
522  EXPECT_EQ("MyRealm1", auth_challenge->realm);
523  EXPECT_EQ("basic", auth_challenge->scheme);
524  return true;
525}
526
527bool CheckBasicProxyAuth(const AuthChallengeInfo* auth_challenge) {
528  if (!auth_challenge)
529    return false;
530  EXPECT_TRUE(auth_challenge->is_proxy);
531  EXPECT_EQ("myproxy:70", auth_challenge->challenger.ToString());
532  EXPECT_EQ("MyRealm1", auth_challenge->realm);
533  EXPECT_EQ("basic", auth_challenge->scheme);
534  return true;
535}
536
537bool CheckDigestServerAuth(const AuthChallengeInfo* auth_challenge) {
538  if (!auth_challenge)
539    return false;
540  EXPECT_FALSE(auth_challenge->is_proxy);
541  EXPECT_EQ("www.google.com:80", auth_challenge->challenger.ToString());
542  EXPECT_EQ("digestive", auth_challenge->realm);
543  EXPECT_EQ("digest", auth_challenge->scheme);
544  return true;
545}
546
547bool CheckNTLMServerAuth(const AuthChallengeInfo* auth_challenge) {
548  if (!auth_challenge)
549    return false;
550  EXPECT_FALSE(auth_challenge->is_proxy);
551  EXPECT_EQ("172.22.68.17:80", auth_challenge->challenger.ToString());
552  EXPECT_EQ(std::string(), auth_challenge->realm);
553  EXPECT_EQ("ntlm", auth_challenge->scheme);
554  return true;
555}
556
557}  // namespace
558
559TEST_P(HttpNetworkTransactionTest, Basic) {
560  scoped_ptr<HttpTransaction> trans(
561      new HttpNetworkTransaction(DEFAULT_PRIORITY,
562                                 CreateSession(&session_deps_)));
563}
564
565TEST_P(HttpNetworkTransactionTest, SimpleGET) {
566  MockRead data_reads[] = {
567    MockRead("HTTP/1.0 200 OK\r\n\r\n"),
568    MockRead("hello world"),
569    MockRead(SYNCHRONOUS, OK),
570  };
571  SimpleGetHelperResult out = SimpleGetHelper(data_reads,
572                                              arraysize(data_reads));
573  EXPECT_EQ(OK, out.rv);
574  EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
575  EXPECT_EQ("hello world", out.response_data);
576}
577
578// Response with no status line.
579TEST_P(HttpNetworkTransactionTest, SimpleGETNoHeaders) {
580  MockRead data_reads[] = {
581    MockRead("hello world"),
582    MockRead(SYNCHRONOUS, OK),
583  };
584  SimpleGetHelperResult out = SimpleGetHelper(data_reads,
585                                              arraysize(data_reads));
586  EXPECT_EQ(OK, out.rv);
587  EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
588  EXPECT_EQ("hello world", out.response_data);
589}
590
591// Allow up to 4 bytes of junk to precede status line.
592TEST_P(HttpNetworkTransactionTest, StatusLineJunk3Bytes) {
593  MockRead data_reads[] = {
594    MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
595    MockRead(SYNCHRONOUS, OK),
596  };
597  SimpleGetHelperResult out = SimpleGetHelper(data_reads,
598                                              arraysize(data_reads));
599  EXPECT_EQ(OK, out.rv);
600  EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
601  EXPECT_EQ("DATA", out.response_data);
602}
603
604// Allow up to 4 bytes of junk to precede status line.
605TEST_P(HttpNetworkTransactionTest, StatusLineJunk4Bytes) {
606  MockRead data_reads[] = {
607    MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
608    MockRead(SYNCHRONOUS, OK),
609  };
610  SimpleGetHelperResult out = SimpleGetHelper(data_reads,
611                                              arraysize(data_reads));
612  EXPECT_EQ(OK, out.rv);
613  EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
614  EXPECT_EQ("DATA", out.response_data);
615}
616
617// Beyond 4 bytes of slop and it should fail to find a status line.
618TEST_P(HttpNetworkTransactionTest, StatusLineJunk5Bytes) {
619  MockRead data_reads[] = {
620    MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
621    MockRead(SYNCHRONOUS, OK),
622  };
623  SimpleGetHelperResult out = SimpleGetHelper(data_reads,
624                                              arraysize(data_reads));
625  EXPECT_EQ(OK, out.rv);
626  EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
627  EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data);
628}
629
630// Same as StatusLineJunk4Bytes, except the read chunks are smaller.
631TEST_P(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) {
632  MockRead data_reads[] = {
633    MockRead("\n"),
634    MockRead("\n"),
635    MockRead("Q"),
636    MockRead("J"),
637    MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
638    MockRead(SYNCHRONOUS, OK),
639  };
640  SimpleGetHelperResult out = SimpleGetHelper(data_reads,
641                                              arraysize(data_reads));
642  EXPECT_EQ(OK, out.rv);
643  EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
644  EXPECT_EQ("DATA", out.response_data);
645}
646
647// Close the connection before enough bytes to have a status line.
648TEST_P(HttpNetworkTransactionTest, StatusLinePartial) {
649  MockRead data_reads[] = {
650    MockRead("HTT"),
651    MockRead(SYNCHRONOUS, OK),
652  };
653  SimpleGetHelperResult out = SimpleGetHelper(data_reads,
654                                              arraysize(data_reads));
655  EXPECT_EQ(OK, out.rv);
656  EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
657  EXPECT_EQ("HTT", out.response_data);
658}
659
660// Simulate a 204 response, lacking a Content-Length header, sent over a
661// persistent connection.  The response should still terminate since a 204
662// cannot have a response body.
663TEST_P(HttpNetworkTransactionTest, StopsReading204) {
664  MockRead data_reads[] = {
665    MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
666    MockRead("junk"),  // Should not be read!!
667    MockRead(SYNCHRONOUS, OK),
668  };
669  SimpleGetHelperResult out = SimpleGetHelper(data_reads,
670                                              arraysize(data_reads));
671  EXPECT_EQ(OK, out.rv);
672  EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line);
673  EXPECT_EQ("", out.response_data);
674}
675
676// A simple request using chunked encoding with some extra data after.
677// (Like might be seen in a pipelined response.)
678TEST_P(HttpNetworkTransactionTest, ChunkedEncoding) {
679  MockRead data_reads[] = {
680    MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
681    MockRead("5\r\nHello\r\n"),
682    MockRead("1\r\n"),
683    MockRead(" \r\n"),
684    MockRead("5\r\nworld\r\n"),
685    MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
686    MockRead(SYNCHRONOUS, OK),
687  };
688  SimpleGetHelperResult out = SimpleGetHelper(data_reads,
689                                              arraysize(data_reads));
690  EXPECT_EQ(OK, out.rv);
691  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
692  EXPECT_EQ("Hello world", out.response_data);
693}
694
695// Next tests deal with http://crbug.com/56344.
696
697TEST_P(HttpNetworkTransactionTest,
698       MultipleContentLengthHeadersNoTransferEncoding) {
699  MockRead data_reads[] = {
700    MockRead("HTTP/1.1 200 OK\r\n"),
701    MockRead("Content-Length: 10\r\n"),
702    MockRead("Content-Length: 5\r\n\r\n"),
703  };
704  SimpleGetHelperResult out = SimpleGetHelper(data_reads,
705                                              arraysize(data_reads));
706  EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, out.rv);
707}
708
709TEST_P(HttpNetworkTransactionTest,
710       DuplicateContentLengthHeadersNoTransferEncoding) {
711  MockRead data_reads[] = {
712    MockRead("HTTP/1.1 200 OK\r\n"),
713    MockRead("Content-Length: 5\r\n"),
714    MockRead("Content-Length: 5\r\n\r\n"),
715    MockRead("Hello"),
716  };
717  SimpleGetHelperResult out = SimpleGetHelper(data_reads,
718                                              arraysize(data_reads));
719  EXPECT_EQ(OK, out.rv);
720  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
721  EXPECT_EQ("Hello", out.response_data);
722}
723
724TEST_P(HttpNetworkTransactionTest,
725       ComplexContentLengthHeadersNoTransferEncoding) {
726  // More than 2 dupes.
727  {
728    MockRead data_reads[] = {
729      MockRead("HTTP/1.1 200 OK\r\n"),
730      MockRead("Content-Length: 5\r\n"),
731      MockRead("Content-Length: 5\r\n"),
732      MockRead("Content-Length: 5\r\n\r\n"),
733      MockRead("Hello"),
734    };
735    SimpleGetHelperResult out = SimpleGetHelper(data_reads,
736                                                arraysize(data_reads));
737    EXPECT_EQ(OK, out.rv);
738    EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
739    EXPECT_EQ("Hello", out.response_data);
740  }
741  // HTTP/1.0
742  {
743    MockRead data_reads[] = {
744      MockRead("HTTP/1.0 200 OK\r\n"),
745      MockRead("Content-Length: 5\r\n"),
746      MockRead("Content-Length: 5\r\n"),
747      MockRead("Content-Length: 5\r\n\r\n"),
748      MockRead("Hello"),
749    };
750    SimpleGetHelperResult out = SimpleGetHelper(data_reads,
751                                                arraysize(data_reads));
752    EXPECT_EQ(OK, out.rv);
753    EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
754    EXPECT_EQ("Hello", out.response_data);
755  }
756  // 2 dupes and one mismatched.
757  {
758    MockRead data_reads[] = {
759      MockRead("HTTP/1.1 200 OK\r\n"),
760      MockRead("Content-Length: 10\r\n"),
761      MockRead("Content-Length: 10\r\n"),
762      MockRead("Content-Length: 5\r\n\r\n"),
763    };
764    SimpleGetHelperResult out = SimpleGetHelper(data_reads,
765                                                arraysize(data_reads));
766    EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, out.rv);
767  }
768}
769
770TEST_P(HttpNetworkTransactionTest,
771       MultipleContentLengthHeadersTransferEncoding) {
772  MockRead data_reads[] = {
773    MockRead("HTTP/1.1 200 OK\r\n"),
774    MockRead("Content-Length: 666\r\n"),
775    MockRead("Content-Length: 1337\r\n"),
776    MockRead("Transfer-Encoding: chunked\r\n\r\n"),
777    MockRead("5\r\nHello\r\n"),
778    MockRead("1\r\n"),
779    MockRead(" \r\n"),
780    MockRead("5\r\nworld\r\n"),
781    MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
782    MockRead(SYNCHRONOUS, OK),
783  };
784  SimpleGetHelperResult out = SimpleGetHelper(data_reads,
785                                              arraysize(data_reads));
786  EXPECT_EQ(OK, out.rv);
787  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
788  EXPECT_EQ("Hello world", out.response_data);
789}
790
791// Next tests deal with http://crbug.com/98895.
792
793// Checks that a single Content-Disposition header results in no error.
794TEST_P(HttpNetworkTransactionTest, SingleContentDispositionHeader) {
795  MockRead data_reads[] = {
796    MockRead("HTTP/1.1 200 OK\r\n"),
797    MockRead("Content-Disposition: attachment;filename=\"salutations.txt\"r\n"),
798    MockRead("Content-Length: 5\r\n\r\n"),
799    MockRead("Hello"),
800  };
801  SimpleGetHelperResult out = SimpleGetHelper(data_reads,
802                                              arraysize(data_reads));
803  EXPECT_EQ(OK, out.rv);
804  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
805  EXPECT_EQ("Hello", out.response_data);
806}
807
808// Checks that two identical Content-Disposition headers result in no error.
809TEST_P(HttpNetworkTransactionTest,
810       TwoIdenticalContentDispositionHeaders) {
811  MockRead data_reads[] = {
812    MockRead("HTTP/1.1 200 OK\r\n"),
813    MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
814    MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
815    MockRead("Content-Length: 5\r\n\r\n"),
816    MockRead("Hello"),
817  };
818  SimpleGetHelperResult out = SimpleGetHelper(data_reads,
819                                              arraysize(data_reads));
820  EXPECT_EQ(OK, out.rv);
821  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
822  EXPECT_EQ("Hello", out.response_data);
823}
824
825// Checks that two distinct Content-Disposition headers result in an error.
826TEST_P(HttpNetworkTransactionTest, TwoDistinctContentDispositionHeaders) {
827  MockRead data_reads[] = {
828    MockRead("HTTP/1.1 200 OK\r\n"),
829    MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
830    MockRead("Content-Disposition: attachment;filename=\"hi.txt\"r\n"),
831    MockRead("Content-Length: 5\r\n\r\n"),
832    MockRead("Hello"),
833  };
834  SimpleGetHelperResult out = SimpleGetHelper(data_reads,
835                                              arraysize(data_reads));
836  EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION, out.rv);
837}
838
839// Checks that two identical Location headers result in no error.
840// Also tests Location header behavior.
841TEST_P(HttpNetworkTransactionTest, TwoIdenticalLocationHeaders) {
842  MockRead data_reads[] = {
843    MockRead("HTTP/1.1 302 Redirect\r\n"),
844    MockRead("Location: http://good.com/\r\n"),
845    MockRead("Location: http://good.com/\r\n"),
846    MockRead("Content-Length: 0\r\n\r\n"),
847    MockRead(SYNCHRONOUS, OK),
848  };
849
850  HttpRequestInfo request;
851  request.method = "GET";
852  request.url = GURL("http://redirect.com/");
853  request.load_flags = 0;
854
855  scoped_ptr<HttpTransaction> trans(
856      new HttpNetworkTransaction(DEFAULT_PRIORITY,
857                                 CreateSession(&session_deps_)));
858
859  StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
860  session_deps_.socket_factory->AddSocketDataProvider(&data);
861
862  TestCompletionCallback callback;
863
864  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
865  EXPECT_EQ(ERR_IO_PENDING, rv);
866
867  EXPECT_EQ(OK, callback.WaitForResult());
868
869  const HttpResponseInfo* response = trans->GetResponseInfo();
870  ASSERT_TRUE(response != NULL && response->headers.get() != NULL);
871  EXPECT_EQ("HTTP/1.1 302 Redirect", response->headers->GetStatusLine());
872  std::string url;
873  EXPECT_TRUE(response->headers->IsRedirect(&url));
874  EXPECT_EQ("http://good.com/", url);
875}
876
877// Checks that two distinct Location headers result in an error.
878TEST_P(HttpNetworkTransactionTest, TwoDistinctLocationHeaders) {
879  MockRead data_reads[] = {
880    MockRead("HTTP/1.1 302 Redirect\r\n"),
881    MockRead("Location: http://good.com/\r\n"),
882    MockRead("Location: http://evil.com/\r\n"),
883    MockRead("Content-Length: 0\r\n\r\n"),
884    MockRead(SYNCHRONOUS, OK),
885  };
886  SimpleGetHelperResult out = SimpleGetHelper(data_reads,
887                                              arraysize(data_reads));
888  EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_LOCATION, out.rv);
889}
890
891// Do a request using the HEAD method. Verify that we don't try to read the
892// message body (since HEAD has none).
893TEST_P(HttpNetworkTransactionTest, Head) {
894  HttpRequestInfo request;
895  request.method = "HEAD";
896  request.url = GURL("http://www.google.com/");
897  request.load_flags = 0;
898
899  scoped_ptr<HttpTransaction> trans(
900      new HttpNetworkTransaction(DEFAULT_PRIORITY,
901                                 CreateSession(&session_deps_)));
902
903  MockWrite data_writes1[] = {
904    MockWrite("HEAD / HTTP/1.1\r\n"
905              "Host: www.google.com\r\n"
906              "Connection: keep-alive\r\n"
907              "Content-Length: 0\r\n\r\n"),
908  };
909  MockRead data_reads1[] = {
910    MockRead("HTTP/1.1 404 Not Found\r\n"),
911    MockRead("Server: Blah\r\n"),
912    MockRead("Content-Length: 1234\r\n\r\n"),
913
914    // No response body because the test stops reading here.
915    MockRead(SYNCHRONOUS, ERR_UNEXPECTED),  // Should not be reached.
916  };
917
918  StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
919                                 data_writes1, arraysize(data_writes1));
920  session_deps_.socket_factory->AddSocketDataProvider(&data1);
921
922  TestCompletionCallback callback1;
923
924  int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
925  EXPECT_EQ(ERR_IO_PENDING, rv);
926
927  rv = callback1.WaitForResult();
928  EXPECT_EQ(OK, rv);
929
930  const HttpResponseInfo* response = trans->GetResponseInfo();
931  ASSERT_TRUE(response != NULL);
932
933  // Check that the headers got parsed.
934  EXPECT_TRUE(response->headers.get() != NULL);
935  EXPECT_EQ(1234, response->headers->GetContentLength());
936  EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine());
937
938  std::string server_header;
939  void* iter = NULL;
940  bool has_server_header = response->headers->EnumerateHeader(
941      &iter, "Server", &server_header);
942  EXPECT_TRUE(has_server_header);
943  EXPECT_EQ("Blah", server_header);
944
945  // Reading should give EOF right away, since there is no message body
946  // (despite non-zero content-length).
947  std::string response_data;
948  rv = ReadTransaction(trans.get(), &response_data);
949  EXPECT_EQ(OK, rv);
950  EXPECT_EQ("", response_data);
951}
952
953TEST_P(HttpNetworkTransactionTest, ReuseConnection) {
954  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
955
956  MockRead data_reads[] = {
957    MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
958    MockRead("hello"),
959    MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
960    MockRead("world"),
961    MockRead(SYNCHRONOUS, OK),
962  };
963  StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
964  session_deps_.socket_factory->AddSocketDataProvider(&data);
965
966  const char* const kExpectedResponseData[] = {
967    "hello", "world"
968  };
969
970  for (int i = 0; i < 2; ++i) {
971    HttpRequestInfo request;
972    request.method = "GET";
973    request.url = GURL("http://www.google.com/");
974    request.load_flags = 0;
975
976    scoped_ptr<HttpTransaction> trans(
977        new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
978
979    TestCompletionCallback callback;
980
981    int rv = trans->Start(&request, callback.callback(), BoundNetLog());
982    EXPECT_EQ(ERR_IO_PENDING, rv);
983
984    rv = callback.WaitForResult();
985    EXPECT_EQ(OK, rv);
986
987    const HttpResponseInfo* response = trans->GetResponseInfo();
988    ASSERT_TRUE(response != NULL);
989
990    EXPECT_TRUE(response->headers.get() != NULL);
991    EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
992
993    std::string response_data;
994    rv = ReadTransaction(trans.get(), &response_data);
995    EXPECT_EQ(OK, rv);
996    EXPECT_EQ(kExpectedResponseData[i], response_data);
997  }
998}
999
1000TEST_P(HttpNetworkTransactionTest, Ignores100) {
1001  ScopedVector<UploadElementReader> element_readers;
1002  element_readers.push_back(new UploadBytesElementReader("foo", 3));
1003  UploadDataStream upload_data_stream(&element_readers, 0);
1004
1005  HttpRequestInfo request;
1006  request.method = "POST";
1007  request.url = GURL("http://www.foo.com/");
1008  request.upload_data_stream = &upload_data_stream;
1009  request.load_flags = 0;
1010
1011  scoped_ptr<HttpTransaction> trans(
1012      new HttpNetworkTransaction(DEFAULT_PRIORITY,
1013                                 CreateSession(&session_deps_)));
1014
1015  MockRead data_reads[] = {
1016    MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
1017    MockRead("HTTP/1.0 200 OK\r\n\r\n"),
1018    MockRead("hello world"),
1019    MockRead(SYNCHRONOUS, OK),
1020  };
1021  StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1022  session_deps_.socket_factory->AddSocketDataProvider(&data);
1023
1024  TestCompletionCallback callback;
1025
1026  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1027  EXPECT_EQ(ERR_IO_PENDING, rv);
1028
1029  rv = callback.WaitForResult();
1030  EXPECT_EQ(OK, rv);
1031
1032  const HttpResponseInfo* response = trans->GetResponseInfo();
1033  ASSERT_TRUE(response != NULL);
1034
1035  EXPECT_TRUE(response->headers.get() != NULL);
1036  EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
1037
1038  std::string response_data;
1039  rv = ReadTransaction(trans.get(), &response_data);
1040  EXPECT_EQ(OK, rv);
1041  EXPECT_EQ("hello world", response_data);
1042}
1043
1044// This test is almost the same as Ignores100 above, but the response contains
1045// a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
1046// HTTP/1.1 and the two status headers are read in one read.
1047TEST_P(HttpNetworkTransactionTest, Ignores1xx) {
1048  HttpRequestInfo request;
1049  request.method = "GET";
1050  request.url = GURL("http://www.foo.com/");
1051  request.load_flags = 0;
1052
1053  scoped_ptr<HttpTransaction> trans(
1054      new HttpNetworkTransaction(DEFAULT_PRIORITY,
1055                                 CreateSession(&session_deps_)));
1056
1057  MockRead data_reads[] = {
1058    MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
1059             "HTTP/1.1 200 OK\r\n\r\n"),
1060    MockRead("hello world"),
1061    MockRead(SYNCHRONOUS, OK),
1062  };
1063  StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1064  session_deps_.socket_factory->AddSocketDataProvider(&data);
1065
1066  TestCompletionCallback callback;
1067
1068  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1069  EXPECT_EQ(ERR_IO_PENDING, rv);
1070
1071  rv = callback.WaitForResult();
1072  EXPECT_EQ(OK, rv);
1073
1074  const HttpResponseInfo* response = trans->GetResponseInfo();
1075  ASSERT_TRUE(response != NULL);
1076
1077  EXPECT_TRUE(response->headers.get() != NULL);
1078  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1079
1080  std::string response_data;
1081  rv = ReadTransaction(trans.get(), &response_data);
1082  EXPECT_EQ(OK, rv);
1083  EXPECT_EQ("hello world", response_data);
1084}
1085
1086TEST_P(HttpNetworkTransactionTest, Incomplete100ThenEOF) {
1087  HttpRequestInfo request;
1088  request.method = "POST";
1089  request.url = GURL("http://www.foo.com/");
1090  request.load_flags = 0;
1091
1092  scoped_ptr<HttpTransaction> trans(
1093      new HttpNetworkTransaction(DEFAULT_PRIORITY,
1094                                 CreateSession(&session_deps_)));
1095
1096  MockRead data_reads[] = {
1097    MockRead(SYNCHRONOUS, "HTTP/1.0 100 Continue\r\n"),
1098    MockRead(ASYNC, 0),
1099  };
1100  StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1101  session_deps_.socket_factory->AddSocketDataProvider(&data);
1102
1103  TestCompletionCallback callback;
1104
1105  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1106  EXPECT_EQ(ERR_IO_PENDING, rv);
1107
1108  rv = callback.WaitForResult();
1109  EXPECT_EQ(OK, rv);
1110
1111  std::string response_data;
1112  rv = ReadTransaction(trans.get(), &response_data);
1113  EXPECT_EQ(OK, rv);
1114  EXPECT_EQ("", response_data);
1115}
1116
1117TEST_P(HttpNetworkTransactionTest, EmptyResponse) {
1118  HttpRequestInfo request;
1119  request.method = "POST";
1120  request.url = GURL("http://www.foo.com/");
1121  request.load_flags = 0;
1122
1123  scoped_ptr<HttpTransaction> trans(
1124      new HttpNetworkTransaction(DEFAULT_PRIORITY,
1125                                 CreateSession(&session_deps_)));
1126
1127  MockRead data_reads[] = {
1128    MockRead(ASYNC, 0),
1129  };
1130  StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1131  session_deps_.socket_factory->AddSocketDataProvider(&data);
1132
1133  TestCompletionCallback callback;
1134
1135  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1136  EXPECT_EQ(ERR_IO_PENDING, rv);
1137
1138  rv = callback.WaitForResult();
1139  EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
1140}
1141
1142void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
1143    const MockWrite* write_failure,
1144    const MockRead* read_failure) {
1145  HttpRequestInfo request;
1146  request.method = "GET";
1147  request.url = GURL("http://www.foo.com/");
1148  request.load_flags = 0;
1149
1150  CapturingNetLog net_log;
1151  session_deps_.net_log = &net_log;
1152  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1153
1154  // Written data for successfully sending both requests.
1155  MockWrite data1_writes[] = {
1156    MockWrite("GET / HTTP/1.1\r\n"
1157              "Host: www.foo.com\r\n"
1158              "Connection: keep-alive\r\n\r\n"),
1159    MockWrite("GET / HTTP/1.1\r\n"
1160              "Host: www.foo.com\r\n"
1161              "Connection: keep-alive\r\n\r\n")
1162  };
1163
1164  // Read results for the first request.
1165  MockRead data1_reads[] = {
1166    MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1167    MockRead("hello"),
1168    MockRead(ASYNC, OK),
1169  };
1170
1171  if (write_failure) {
1172    ASSERT_TRUE(!read_failure);
1173    data1_writes[1] = *write_failure;
1174  } else {
1175    ASSERT_TRUE(read_failure);
1176    data1_reads[2] = *read_failure;
1177  }
1178
1179  StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads),
1180                                 data1_writes, arraysize(data1_writes));
1181  session_deps_.socket_factory->AddSocketDataProvider(&data1);
1182
1183  MockRead data2_reads[] = {
1184    MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1185    MockRead("world"),
1186    MockRead(ASYNC, OK),
1187  };
1188  StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
1189  session_deps_.socket_factory->AddSocketDataProvider(&data2);
1190
1191  const char* kExpectedResponseData[] = {
1192    "hello", "world"
1193  };
1194
1195  uint32 first_socket_log_id = NetLog::Source::kInvalidId;
1196  for (int i = 0; i < 2; ++i) {
1197    TestCompletionCallback callback;
1198
1199    scoped_ptr<HttpTransaction> trans(
1200        new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1201
1202    int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1203    EXPECT_EQ(ERR_IO_PENDING, rv);
1204
1205    rv = callback.WaitForResult();
1206    EXPECT_EQ(OK, rv);
1207
1208    LoadTimingInfo load_timing_info;
1209    EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
1210    TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
1211    if (i == 0) {
1212      first_socket_log_id = load_timing_info.socket_log_id;
1213    } else {
1214      // The second request should be using a new socket.
1215      EXPECT_NE(first_socket_log_id, load_timing_info.socket_log_id);
1216    }
1217
1218    const HttpResponseInfo* response = trans->GetResponseInfo();
1219    ASSERT_TRUE(response != NULL);
1220
1221    EXPECT_TRUE(response->headers.get() != NULL);
1222    EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1223
1224    std::string response_data;
1225    rv = ReadTransaction(trans.get(), &response_data);
1226    EXPECT_EQ(OK, rv);
1227    EXPECT_EQ(kExpectedResponseData[i], response_data);
1228  }
1229}
1230
1231TEST_P(HttpNetworkTransactionTest,
1232       KeepAliveConnectionNotConnectedOnWrite) {
1233  MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
1234  KeepAliveConnectionResendRequestTest(&write_failure, NULL);
1235}
1236
1237TEST_P(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
1238  MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
1239  KeepAliveConnectionResendRequestTest(NULL, &read_failure);
1240}
1241
1242TEST_P(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
1243  MockRead read_failure(SYNCHRONOUS, OK);  // EOF
1244  KeepAliveConnectionResendRequestTest(NULL, &read_failure);
1245}
1246
1247TEST_P(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
1248  HttpRequestInfo request;
1249  request.method = "GET";
1250  request.url = GURL("http://www.google.com/");
1251  request.load_flags = 0;
1252
1253  scoped_ptr<HttpTransaction> trans(
1254      new HttpNetworkTransaction(DEFAULT_PRIORITY,
1255                                 CreateSession(&session_deps_)));
1256
1257  MockRead data_reads[] = {
1258    MockRead(ASYNC, ERR_CONNECTION_RESET),
1259    MockRead("HTTP/1.0 200 OK\r\n\r\n"),  // Should not be used
1260    MockRead("hello world"),
1261    MockRead(SYNCHRONOUS, OK),
1262  };
1263  StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1264  session_deps_.socket_factory->AddSocketDataProvider(&data);
1265
1266  TestCompletionCallback callback;
1267
1268  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1269  EXPECT_EQ(ERR_IO_PENDING, rv);
1270
1271  rv = callback.WaitForResult();
1272  EXPECT_EQ(ERR_CONNECTION_RESET, rv);
1273
1274  const HttpResponseInfo* response = trans->GetResponseInfo();
1275  EXPECT_TRUE(response == NULL);
1276}
1277
1278// What do various browsers do when the server closes a non-keepalive
1279// connection without sending any response header or body?
1280//
1281// IE7: error page
1282// Safari 3.1.2 (Windows): error page
1283// Firefox 3.0.1: blank page
1284// Opera 9.52: after five attempts, blank page
1285// Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
1286// Us: error page (EMPTY_RESPONSE)
1287TEST_P(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
1288  MockRead data_reads[] = {
1289    MockRead(SYNCHRONOUS, OK),  // EOF
1290    MockRead("HTTP/1.0 200 OK\r\n\r\n"),  // Should not be used
1291    MockRead("hello world"),
1292    MockRead(SYNCHRONOUS, OK),
1293  };
1294  SimpleGetHelperResult out = SimpleGetHelper(data_reads,
1295                                              arraysize(data_reads));
1296  EXPECT_EQ(ERR_EMPTY_RESPONSE, out.rv);
1297}
1298
1299// Next 2 cases (KeepAliveEarlyClose and KeepAliveEarlyClose2) are regression
1300// tests. There was a bug causing HttpNetworkTransaction to hang in the
1301// destructor in such situations.
1302// See http://crbug.com/154712 and http://crbug.com/156609.
1303TEST_P(HttpNetworkTransactionTest, KeepAliveEarlyClose) {
1304  HttpRequestInfo request;
1305  request.method = "GET";
1306  request.url = GURL("http://www.google.com/");
1307  request.load_flags = 0;
1308
1309  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1310  scoped_ptr<HttpTransaction> trans(
1311      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1312
1313  MockRead data_reads[] = {
1314    MockRead("HTTP/1.0 200 OK\r\n"),
1315    MockRead("Connection: keep-alive\r\n"),
1316    MockRead("Content-Length: 100\r\n\r\n"),
1317    MockRead("hello"),
1318    MockRead(SYNCHRONOUS, 0),
1319  };
1320  StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1321  session_deps_.socket_factory->AddSocketDataProvider(&data);
1322
1323  TestCompletionCallback callback;
1324
1325  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1326  EXPECT_EQ(ERR_IO_PENDING, rv);
1327
1328  rv = callback.WaitForResult();
1329  EXPECT_EQ(OK, rv);
1330
1331  scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(100));
1332  rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
1333  if (rv == ERR_IO_PENDING)
1334    rv = callback.WaitForResult();
1335  EXPECT_EQ(5, rv);
1336  rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
1337  EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH, rv);
1338
1339  trans.reset();
1340  base::MessageLoop::current()->RunUntilIdle();
1341  EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
1342}
1343
1344TEST_P(HttpNetworkTransactionTest, KeepAliveEarlyClose2) {
1345  HttpRequestInfo request;
1346  request.method = "GET";
1347  request.url = GURL("http://www.google.com/");
1348  request.load_flags = 0;
1349
1350  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1351  scoped_ptr<HttpTransaction> trans(
1352      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1353
1354  MockRead data_reads[] = {
1355    MockRead("HTTP/1.0 200 OK\r\n"),
1356    MockRead("Connection: keep-alive\r\n"),
1357    MockRead("Content-Length: 100\r\n\r\n"),
1358    MockRead(SYNCHRONOUS, 0),
1359  };
1360  StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1361  session_deps_.socket_factory->AddSocketDataProvider(&data);
1362
1363  TestCompletionCallback callback;
1364
1365  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1366  EXPECT_EQ(ERR_IO_PENDING, rv);
1367
1368  rv = callback.WaitForResult();
1369  EXPECT_EQ(OK, rv);
1370
1371  scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(100));
1372  rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
1373  if (rv == ERR_IO_PENDING)
1374    rv = callback.WaitForResult();
1375  EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH, rv);
1376
1377  trans.reset();
1378  base::MessageLoop::current()->RunUntilIdle();
1379  EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
1380}
1381
1382// Test that we correctly reuse a keep-alive connection after not explicitly
1383// reading the body.
1384TEST_P(HttpNetworkTransactionTest, KeepAliveAfterUnreadBody) {
1385  HttpRequestInfo request;
1386  request.method = "GET";
1387  request.url = GURL("http://www.foo.com/");
1388  request.load_flags = 0;
1389
1390  CapturingNetLog net_log;
1391  session_deps_.net_log = &net_log;
1392  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1393
1394  // Note that because all these reads happen in the same
1395  // StaticSocketDataProvider, it shows that the same socket is being reused for
1396  // all transactions.
1397  MockRead data1_reads[] = {
1398    MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
1399    MockRead("HTTP/1.1 205 Reset Content\r\n\r\n"),
1400    MockRead("HTTP/1.1 304 Not Modified\r\n\r\n"),
1401    MockRead("HTTP/1.1 302 Found\r\n"
1402             "Content-Length: 0\r\n\r\n"),
1403    MockRead("HTTP/1.1 302 Found\r\n"
1404             "Content-Length: 5\r\n\r\n"
1405             "hello"),
1406    MockRead("HTTP/1.1 301 Moved Permanently\r\n"
1407             "Content-Length: 0\r\n\r\n"),
1408    MockRead("HTTP/1.1 301 Moved Permanently\r\n"
1409             "Content-Length: 5\r\n\r\n"
1410             "hello"),
1411    MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1412    MockRead("hello"),
1413  };
1414  StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), NULL, 0);
1415  session_deps_.socket_factory->AddSocketDataProvider(&data1);
1416
1417  MockRead data2_reads[] = {
1418    MockRead(SYNCHRONOUS, ERR_UNEXPECTED),  // Should not be reached.
1419  };
1420  StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
1421  session_deps_.socket_factory->AddSocketDataProvider(&data2);
1422
1423  const int kNumUnreadBodies = arraysize(data1_reads) - 2;
1424  std::string response_lines[kNumUnreadBodies];
1425
1426  uint32 first_socket_log_id = NetLog::Source::kInvalidId;
1427  for (size_t i = 0; i < arraysize(data1_reads) - 2; ++i) {
1428    TestCompletionCallback callback;
1429
1430    scoped_ptr<HttpTransaction> trans(
1431        new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1432
1433    int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1434    EXPECT_EQ(ERR_IO_PENDING, rv);
1435
1436    rv = callback.WaitForResult();
1437    EXPECT_EQ(OK, rv);
1438
1439    LoadTimingInfo load_timing_info;
1440    EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
1441    if (i == 0) {
1442      TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
1443      first_socket_log_id = load_timing_info.socket_log_id;
1444    } else {
1445      TestLoadTimingReused(load_timing_info);
1446      EXPECT_EQ(first_socket_log_id, load_timing_info.socket_log_id);
1447    }
1448
1449    const HttpResponseInfo* response = trans->GetResponseInfo();
1450    ASSERT_TRUE(response != NULL);
1451
1452    ASSERT_TRUE(response->headers.get() != NULL);
1453    response_lines[i] = response->headers->GetStatusLine();
1454
1455    // We intentionally don't read the response bodies.
1456  }
1457
1458  const char* const kStatusLines[] = {
1459    "HTTP/1.1 204 No Content",
1460    "HTTP/1.1 205 Reset Content",
1461    "HTTP/1.1 304 Not Modified",
1462    "HTTP/1.1 302 Found",
1463    "HTTP/1.1 302 Found",
1464    "HTTP/1.1 301 Moved Permanently",
1465    "HTTP/1.1 301 Moved Permanently",
1466  };
1467
1468  COMPILE_ASSERT(kNumUnreadBodies == arraysize(kStatusLines),
1469                 forgot_to_update_kStatusLines);
1470
1471  for (int i = 0; i < kNumUnreadBodies; ++i)
1472    EXPECT_EQ(kStatusLines[i], response_lines[i]);
1473
1474  TestCompletionCallback callback;
1475  scoped_ptr<HttpTransaction> trans(
1476      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1477  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1478  EXPECT_EQ(ERR_IO_PENDING, rv);
1479  rv = callback.WaitForResult();
1480  EXPECT_EQ(OK, rv);
1481  const HttpResponseInfo* response = trans->GetResponseInfo();
1482  ASSERT_TRUE(response != NULL);
1483  ASSERT_TRUE(response->headers.get() != NULL);
1484  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1485  std::string response_data;
1486  rv = ReadTransaction(trans.get(), &response_data);
1487  EXPECT_EQ(OK, rv);
1488  EXPECT_EQ("hello", response_data);
1489}
1490
1491// Test the request-challenge-retry sequence for basic auth.
1492// (basic auth is the easiest to mock, because it has no randomness).
1493TEST_P(HttpNetworkTransactionTest, BasicAuth) {
1494  HttpRequestInfo request;
1495  request.method = "GET";
1496  request.url = GURL("http://www.google.com/");
1497  request.load_flags = 0;
1498
1499  CapturingNetLog log;
1500  session_deps_.net_log = &log;
1501  scoped_ptr<HttpTransaction> trans(
1502      new HttpNetworkTransaction(DEFAULT_PRIORITY,
1503                                 CreateSession(&session_deps_)));
1504
1505  MockWrite data_writes1[] = {
1506    MockWrite("GET / HTTP/1.1\r\n"
1507              "Host: www.google.com\r\n"
1508              "Connection: keep-alive\r\n\r\n"),
1509  };
1510
1511  MockRead data_reads1[] = {
1512    MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1513    // Give a couple authenticate options (only the middle one is actually
1514    // supported).
1515    MockRead("WWW-Authenticate: Basic invalid\r\n"),  // Malformed.
1516    MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1517    MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
1518    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1519    // Large content-length -- won't matter, as connection will be reset.
1520    MockRead("Content-Length: 10000\r\n\r\n"),
1521    MockRead(SYNCHRONOUS, ERR_FAILED),
1522  };
1523
1524  // After calling trans->RestartWithAuth(), this is the request we should
1525  // be issuing -- the final header line contains the credentials.
1526  MockWrite data_writes2[] = {
1527    MockWrite("GET / HTTP/1.1\r\n"
1528              "Host: www.google.com\r\n"
1529              "Connection: keep-alive\r\n"
1530              "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1531  };
1532
1533  // Lastly, the server responds with the actual content.
1534  MockRead data_reads2[] = {
1535    MockRead("HTTP/1.0 200 OK\r\n"),
1536    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1537    MockRead("Content-Length: 100\r\n\r\n"),
1538    MockRead(SYNCHRONOUS, OK),
1539  };
1540
1541  StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1542                                 data_writes1, arraysize(data_writes1));
1543  StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1544                                 data_writes2, arraysize(data_writes2));
1545  session_deps_.socket_factory->AddSocketDataProvider(&data1);
1546  session_deps_.socket_factory->AddSocketDataProvider(&data2);
1547
1548  TestCompletionCallback callback1;
1549
1550  int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
1551  EXPECT_EQ(ERR_IO_PENDING, rv);
1552
1553  rv = callback1.WaitForResult();
1554  EXPECT_EQ(OK, rv);
1555
1556  LoadTimingInfo load_timing_info1;
1557  EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info1));
1558  TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
1559
1560  const HttpResponseInfo* response = trans->GetResponseInfo();
1561  ASSERT_TRUE(response != NULL);
1562  EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
1563
1564  TestCompletionCallback callback2;
1565
1566  rv = trans->RestartWithAuth(
1567      AuthCredentials(kFoo, kBar), callback2.callback());
1568  EXPECT_EQ(ERR_IO_PENDING, rv);
1569
1570  rv = callback2.WaitForResult();
1571  EXPECT_EQ(OK, rv);
1572
1573  LoadTimingInfo load_timing_info2;
1574  EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info2));
1575  TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_DNS_TIMES);
1576  // The load timing after restart should have a new socket ID, and times after
1577  // those of the first load timing.
1578  EXPECT_LE(load_timing_info1.receive_headers_end,
1579            load_timing_info2.connect_timing.connect_start);
1580  EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
1581
1582  response = trans->GetResponseInfo();
1583  ASSERT_TRUE(response != NULL);
1584  EXPECT_TRUE(response->auth_challenge.get() == NULL);
1585  EXPECT_EQ(100, response->headers->GetContentLength());
1586}
1587
1588TEST_P(HttpNetworkTransactionTest, DoNotSendAuth) {
1589  HttpRequestInfo request;
1590  request.method = "GET";
1591  request.url = GURL("http://www.google.com/");
1592  request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
1593
1594  scoped_ptr<HttpTransaction> trans(
1595      new HttpNetworkTransaction(DEFAULT_PRIORITY,
1596                                 CreateSession(&session_deps_)));
1597
1598  MockWrite data_writes[] = {
1599    MockWrite("GET / HTTP/1.1\r\n"
1600              "Host: www.google.com\r\n"
1601              "Connection: keep-alive\r\n\r\n"),
1602  };
1603
1604  MockRead data_reads[] = {
1605    MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1606    MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1607    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1608    // Large content-length -- won't matter, as connection will be reset.
1609    MockRead("Content-Length: 10000\r\n\r\n"),
1610    MockRead(SYNCHRONOUS, ERR_FAILED),
1611  };
1612
1613  StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1614                                data_writes, arraysize(data_writes));
1615  session_deps_.socket_factory->AddSocketDataProvider(&data);
1616  TestCompletionCallback callback;
1617
1618  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1619  EXPECT_EQ(ERR_IO_PENDING, rv);
1620
1621  rv = callback.WaitForResult();
1622  EXPECT_EQ(0, rv);
1623
1624  const HttpResponseInfo* response = trans->GetResponseInfo();
1625  ASSERT_TRUE(response != NULL);
1626  EXPECT_TRUE(response->auth_challenge.get() == NULL);
1627}
1628
1629// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1630// connection.
1631TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
1632  HttpRequestInfo request;
1633  request.method = "GET";
1634  request.url = GURL("http://www.google.com/");
1635  request.load_flags = 0;
1636
1637  CapturingNetLog log;
1638  session_deps_.net_log = &log;
1639  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1640
1641  MockWrite data_writes1[] = {
1642    MockWrite("GET / HTTP/1.1\r\n"
1643              "Host: www.google.com\r\n"
1644              "Connection: keep-alive\r\n\r\n"),
1645
1646    // After calling trans->RestartWithAuth(), this is the request we should
1647    // be issuing -- the final header line contains the credentials.
1648    MockWrite("GET / HTTP/1.1\r\n"
1649              "Host: www.google.com\r\n"
1650              "Connection: keep-alive\r\n"
1651              "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1652  };
1653
1654  MockRead data_reads1[] = {
1655    MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1656    MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1657    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1658    MockRead("Content-Length: 14\r\n\r\n"),
1659    MockRead("Unauthorized\r\n"),
1660
1661    // Lastly, the server responds with the actual content.
1662    MockRead("HTTP/1.1 200 OK\r\n"),
1663    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1664    MockRead("Content-Length: 5\r\n\r\n"),
1665    MockRead("Hello"),
1666  };
1667
1668  // If there is a regression where we disconnect a Keep-Alive
1669  // connection during an auth roundtrip, we'll end up reading this.
1670  MockRead data_reads2[] = {
1671    MockRead(SYNCHRONOUS, ERR_FAILED),
1672  };
1673
1674  StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1675                                 data_writes1, arraysize(data_writes1));
1676  StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1677                                 NULL, 0);
1678  session_deps_.socket_factory->AddSocketDataProvider(&data1);
1679  session_deps_.socket_factory->AddSocketDataProvider(&data2);
1680
1681  TestCompletionCallback callback1;
1682
1683  scoped_ptr<HttpTransaction> trans(
1684      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1685  int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
1686  EXPECT_EQ(ERR_IO_PENDING, rv);
1687
1688  rv = callback1.WaitForResult();
1689  EXPECT_EQ(OK, rv);
1690
1691  LoadTimingInfo load_timing_info1;
1692  EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info1));
1693  TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
1694
1695  const HttpResponseInfo* response = trans->GetResponseInfo();
1696  ASSERT_TRUE(response != NULL);
1697  EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
1698
1699  TestCompletionCallback callback2;
1700
1701  rv = trans->RestartWithAuth(
1702      AuthCredentials(kFoo, kBar), callback2.callback());
1703  EXPECT_EQ(ERR_IO_PENDING, rv);
1704
1705  rv = callback2.WaitForResult();
1706  EXPECT_EQ(OK, rv);
1707
1708  LoadTimingInfo load_timing_info2;
1709  EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info2));
1710  TestLoadTimingReused(load_timing_info2);
1711  // The load timing after restart should have the same socket ID, and times
1712  // those of the first load timing.
1713  EXPECT_LE(load_timing_info1.receive_headers_end,
1714            load_timing_info2.send_start);
1715  EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
1716
1717  response = trans->GetResponseInfo();
1718  ASSERT_TRUE(response != NULL);
1719  EXPECT_TRUE(response->auth_challenge.get() == NULL);
1720  EXPECT_EQ(5, response->headers->GetContentLength());
1721}
1722
1723// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1724// connection and with no response body to drain.
1725TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
1726  HttpRequestInfo request;
1727  request.method = "GET";
1728  request.url = GURL("http://www.google.com/");
1729  request.load_flags = 0;
1730
1731  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1732
1733  MockWrite data_writes1[] = {
1734    MockWrite("GET / HTTP/1.1\r\n"
1735              "Host: www.google.com\r\n"
1736              "Connection: keep-alive\r\n\r\n"),
1737
1738    // After calling trans->RestartWithAuth(), this is the request we should
1739    // be issuing -- the final header line contains the credentials.
1740    MockWrite("GET / HTTP/1.1\r\n"
1741              "Host: www.google.com\r\n"
1742              "Connection: keep-alive\r\n"
1743              "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1744  };
1745
1746  MockRead data_reads1[] = {
1747    MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1748    MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1749    MockRead("Content-Length: 0\r\n\r\n"),  // No response body.
1750
1751    // Lastly, the server responds with the actual content.
1752    MockRead("HTTP/1.1 200 OK\r\n"),
1753    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1754    MockRead("Content-Length: 5\r\n\r\n"),
1755    MockRead("hello"),
1756  };
1757
1758  // An incorrect reconnect would cause this to be read.
1759  MockRead data_reads2[] = {
1760    MockRead(SYNCHRONOUS, ERR_FAILED),
1761  };
1762
1763  StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1764                                 data_writes1, arraysize(data_writes1));
1765  StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1766                                 NULL, 0);
1767  session_deps_.socket_factory->AddSocketDataProvider(&data1);
1768  session_deps_.socket_factory->AddSocketDataProvider(&data2);
1769
1770  TestCompletionCallback callback1;
1771
1772  scoped_ptr<HttpTransaction> trans(
1773      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1774  int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
1775  EXPECT_EQ(ERR_IO_PENDING, rv);
1776
1777  rv = callback1.WaitForResult();
1778  EXPECT_EQ(OK, rv);
1779
1780  const HttpResponseInfo* response = trans->GetResponseInfo();
1781  ASSERT_TRUE(response != NULL);
1782  EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
1783
1784  TestCompletionCallback callback2;
1785
1786  rv = trans->RestartWithAuth(
1787      AuthCredentials(kFoo, kBar), callback2.callback());
1788  EXPECT_EQ(ERR_IO_PENDING, rv);
1789
1790  rv = callback2.WaitForResult();
1791  EXPECT_EQ(OK, rv);
1792
1793  response = trans->GetResponseInfo();
1794  ASSERT_TRUE(response != NULL);
1795  EXPECT_TRUE(response->auth_challenge.get() == NULL);
1796  EXPECT_EQ(5, response->headers->GetContentLength());
1797}
1798
1799// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1800// connection and with a large response body to drain.
1801TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
1802  HttpRequestInfo request;
1803  request.method = "GET";
1804  request.url = GURL("http://www.google.com/");
1805  request.load_flags = 0;
1806
1807  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1808
1809  MockWrite data_writes1[] = {
1810    MockWrite("GET / HTTP/1.1\r\n"
1811              "Host: www.google.com\r\n"
1812              "Connection: keep-alive\r\n\r\n"),
1813
1814    // After calling trans->RestartWithAuth(), this is the request we should
1815    // be issuing -- the final header line contains the credentials.
1816    MockWrite("GET / HTTP/1.1\r\n"
1817              "Host: www.google.com\r\n"
1818              "Connection: keep-alive\r\n"
1819              "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1820  };
1821
1822  // Respond with 5 kb of response body.
1823  std::string large_body_string("Unauthorized");
1824  large_body_string.append(5 * 1024, ' ');
1825  large_body_string.append("\r\n");
1826
1827  MockRead data_reads1[] = {
1828    MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1829    MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1830    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1831    // 5134 = 12 + 5 * 1024 + 2
1832    MockRead("Content-Length: 5134\r\n\r\n"),
1833    MockRead(ASYNC, large_body_string.data(), large_body_string.size()),
1834
1835    // Lastly, the server responds with the actual content.
1836    MockRead("HTTP/1.1 200 OK\r\n"),
1837    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1838    MockRead("Content-Length: 5\r\n\r\n"),
1839    MockRead("hello"),
1840  };
1841
1842  // An incorrect reconnect would cause this to be read.
1843  MockRead data_reads2[] = {
1844    MockRead(SYNCHRONOUS, ERR_FAILED),
1845  };
1846
1847  StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1848                                 data_writes1, arraysize(data_writes1));
1849  StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1850                                 NULL, 0);
1851  session_deps_.socket_factory->AddSocketDataProvider(&data1);
1852  session_deps_.socket_factory->AddSocketDataProvider(&data2);
1853
1854  TestCompletionCallback callback1;
1855
1856  scoped_ptr<HttpTransaction> trans(
1857      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1858  int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
1859  EXPECT_EQ(ERR_IO_PENDING, rv);
1860
1861  rv = callback1.WaitForResult();
1862  EXPECT_EQ(OK, rv);
1863
1864  const HttpResponseInfo* response = trans->GetResponseInfo();
1865  ASSERT_TRUE(response != NULL);
1866  EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
1867
1868  TestCompletionCallback callback2;
1869
1870  rv = trans->RestartWithAuth(
1871      AuthCredentials(kFoo, kBar), callback2.callback());
1872  EXPECT_EQ(ERR_IO_PENDING, rv);
1873
1874  rv = callback2.WaitForResult();
1875  EXPECT_EQ(OK, rv);
1876
1877  response = trans->GetResponseInfo();
1878  ASSERT_TRUE(response != NULL);
1879  EXPECT_TRUE(response->auth_challenge.get() == NULL);
1880  EXPECT_EQ(5, response->headers->GetContentLength());
1881}
1882
1883// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1884// connection, but the server gets impatient and closes the connection.
1885TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) {
1886  HttpRequestInfo request;
1887  request.method = "GET";
1888  request.url = GURL("http://www.google.com/");
1889  request.load_flags = 0;
1890
1891  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1892
1893  MockWrite data_writes1[] = {
1894    MockWrite("GET / HTTP/1.1\r\n"
1895              "Host: www.google.com\r\n"
1896              "Connection: keep-alive\r\n\r\n"),
1897    // This simulates the seemingly successful write to a closed connection
1898    // if the bug is not fixed.
1899    MockWrite("GET / HTTP/1.1\r\n"
1900              "Host: www.google.com\r\n"
1901              "Connection: keep-alive\r\n"
1902              "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1903  };
1904
1905  MockRead data_reads1[] = {
1906    MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1907    MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1908    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1909    MockRead("Content-Length: 14\r\n\r\n"),
1910    // Tell MockTCPClientSocket to simulate the server closing the connection.
1911    MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
1912    MockRead("Unauthorized\r\n"),
1913    MockRead(SYNCHRONOUS, OK),  // The server closes the connection.
1914  };
1915
1916  // After calling trans->RestartWithAuth(), this is the request we should
1917  // be issuing -- the final header line contains the credentials.
1918  MockWrite data_writes2[] = {
1919    MockWrite("GET / HTTP/1.1\r\n"
1920              "Host: www.google.com\r\n"
1921              "Connection: keep-alive\r\n"
1922              "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1923  };
1924
1925  // Lastly, the server responds with the actual content.
1926  MockRead data_reads2[] = {
1927    MockRead("HTTP/1.1 200 OK\r\n"),
1928    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1929    MockRead("Content-Length: 5\r\n\r\n"),
1930    MockRead("hello"),
1931  };
1932
1933  StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1934                                 data_writes1, arraysize(data_writes1));
1935  StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1936                                 data_writes2, arraysize(data_writes2));
1937  session_deps_.socket_factory->AddSocketDataProvider(&data1);
1938  session_deps_.socket_factory->AddSocketDataProvider(&data2);
1939
1940  TestCompletionCallback callback1;
1941
1942  scoped_ptr<HttpTransaction> trans(
1943      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1944  int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
1945  EXPECT_EQ(ERR_IO_PENDING, rv);
1946
1947  rv = callback1.WaitForResult();
1948  EXPECT_EQ(OK, rv);
1949
1950  const HttpResponseInfo* response = trans->GetResponseInfo();
1951  ASSERT_TRUE(response != NULL);
1952  EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
1953
1954  TestCompletionCallback callback2;
1955
1956  rv = trans->RestartWithAuth(
1957      AuthCredentials(kFoo, kBar), callback2.callback());
1958  EXPECT_EQ(ERR_IO_PENDING, rv);
1959
1960  rv = callback2.WaitForResult();
1961  EXPECT_EQ(OK, rv);
1962
1963  response = trans->GetResponseInfo();
1964  ASSERT_TRUE(response != NULL);
1965  EXPECT_TRUE(response->auth_challenge.get() == NULL);
1966  EXPECT_EQ(5, response->headers->GetContentLength());
1967}
1968
1969// Test the request-challenge-retry sequence for basic auth, over a connection
1970// that requires a restart when setting up an SSL tunnel.
1971TEST_P(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAlive) {
1972  HttpRequestInfo request;
1973  request.method = "GET";
1974  request.url = GURL("https://www.google.com/");
1975  // when the no authentication data flag is set.
1976  request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
1977
1978  // Configure against proxy server "myproxy:70".
1979  session_deps_.proxy_service.reset(
1980      ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
1981  CapturingBoundNetLog log;
1982  session_deps_.net_log = log.bound().net_log();
1983  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1984
1985  // Since we have proxy, should try to establish tunnel.
1986  MockWrite data_writes1[] = {
1987    MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1988              "Host: www.google.com\r\n"
1989              "Proxy-Connection: keep-alive\r\n\r\n"),
1990
1991    // After calling trans->RestartWithAuth(), this is the request we should
1992    // be issuing -- the final header line contains the credentials.
1993    MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1994              "Host: www.google.com\r\n"
1995              "Proxy-Connection: keep-alive\r\n"
1996              "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1997
1998    MockWrite("GET / HTTP/1.1\r\n"
1999              "Host: www.google.com\r\n"
2000              "Connection: keep-alive\r\n\r\n"),
2001  };
2002
2003  // The proxy responds to the connect with a 407, using a persistent
2004  // connection.
2005  MockRead data_reads1[] = {
2006    // No credentials.
2007    MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2008    MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2009    MockRead("Proxy-Connection: close\r\n\r\n"),
2010
2011    MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2012
2013    MockRead("HTTP/1.1 200 OK\r\n"),
2014    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2015    MockRead("Content-Length: 5\r\n\r\n"),
2016    MockRead(SYNCHRONOUS, "hello"),
2017  };
2018
2019  StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2020                                 data_writes1, arraysize(data_writes1));
2021  session_deps_.socket_factory->AddSocketDataProvider(&data1);
2022  SSLSocketDataProvider ssl(ASYNC, OK);
2023  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2024
2025  TestCompletionCallback callback1;
2026
2027  scoped_ptr<HttpTransaction> trans(
2028      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2029
2030  int rv = trans->Start(&request, callback1.callback(), log.bound());
2031  EXPECT_EQ(ERR_IO_PENDING, rv);
2032
2033  rv = callback1.WaitForResult();
2034  EXPECT_EQ(OK, rv);
2035  net::CapturingNetLog::CapturedEntryList entries;
2036  log.GetEntries(&entries);
2037  size_t pos = ExpectLogContainsSomewhere(
2038      entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
2039      NetLog::PHASE_NONE);
2040  ExpectLogContainsSomewhere(
2041      entries, pos,
2042      NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
2043      NetLog::PHASE_NONE);
2044
2045  const HttpResponseInfo* response = trans->GetResponseInfo();
2046  ASSERT_TRUE(response != NULL);
2047  ASSERT_FALSE(response->headers.get() == NULL);
2048  EXPECT_EQ(407, response->headers->response_code());
2049  EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2050  EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2051
2052  LoadTimingInfo load_timing_info;
2053  // CONNECT requests and responses are handled at the connect job level, so
2054  // the transaction does not yet have a connection.
2055  EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
2056
2057  TestCompletionCallback callback2;
2058
2059  rv = trans->RestartWithAuth(
2060      AuthCredentials(kFoo, kBar), callback2.callback());
2061  EXPECT_EQ(ERR_IO_PENDING, rv);
2062
2063  rv = callback2.WaitForResult();
2064  EXPECT_EQ(OK, rv);
2065
2066  response = trans->GetResponseInfo();
2067  ASSERT_TRUE(response != NULL);
2068
2069  EXPECT_TRUE(response->headers->IsKeepAlive());
2070  EXPECT_EQ(200, response->headers->response_code());
2071  EXPECT_EQ(5, response->headers->GetContentLength());
2072  EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2073
2074  // The password prompt info should not be set.
2075  EXPECT_TRUE(response->auth_challenge.get() == NULL);
2076
2077  EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
2078  TestLoadTimingNotReusedWithPac(load_timing_info,
2079                                 CONNECT_TIMING_HAS_SSL_TIMES);
2080
2081  trans.reset();
2082  session->CloseAllConnections();
2083}
2084
2085// Test the request-challenge-retry sequence for basic auth, over a keep-alive
2086// proxy connection, when setting up an SSL tunnel.
2087TEST_P(HttpNetworkTransactionTest, BasicAuthProxyKeepAlive) {
2088  HttpRequestInfo request;
2089  request.method = "GET";
2090  request.url = GURL("https://www.google.com/");
2091  // Ensure that proxy authentication is attempted even
2092  // when the no authentication data flag is set.
2093  request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
2094
2095  // Configure against proxy server "myproxy:70".
2096  session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
2097  CapturingBoundNetLog log;
2098  session_deps_.net_log = log.bound().net_log();
2099  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2100
2101  scoped_ptr<HttpTransaction> trans(
2102      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2103
2104  // Since we have proxy, should try to establish tunnel.
2105  MockWrite data_writes1[] = {
2106    MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2107              "Host: www.google.com\r\n"
2108              "Proxy-Connection: keep-alive\r\n\r\n"),
2109
2110    // After calling trans->RestartWithAuth(), this is the request we should
2111    // be issuing -- the final header line contains the credentials.
2112    MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2113              "Host: www.google.com\r\n"
2114              "Proxy-Connection: keep-alive\r\n"
2115              "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
2116  };
2117
2118  // The proxy responds to the connect with a 407, using a persistent
2119  // connection.
2120  MockRead data_reads1[] = {
2121    // No credentials.
2122    MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2123    MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2124    MockRead("Content-Length: 10\r\n\r\n"),
2125    MockRead("0123456789"),
2126
2127    // Wrong credentials (wrong password).
2128    MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2129    MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2130    MockRead("Content-Length: 10\r\n\r\n"),
2131    // No response body because the test stops reading here.
2132    MockRead(SYNCHRONOUS, ERR_UNEXPECTED),  // Should not be reached.
2133  };
2134
2135  StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2136                                 data_writes1, arraysize(data_writes1));
2137  session_deps_.socket_factory->AddSocketDataProvider(&data1);
2138
2139  TestCompletionCallback callback1;
2140
2141  int rv = trans->Start(&request, callback1.callback(), log.bound());
2142  EXPECT_EQ(ERR_IO_PENDING, rv);
2143
2144  rv = callback1.WaitForResult();
2145  EXPECT_EQ(OK, rv);
2146  net::CapturingNetLog::CapturedEntryList entries;
2147  log.GetEntries(&entries);
2148  size_t pos = ExpectLogContainsSomewhere(
2149      entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
2150      NetLog::PHASE_NONE);
2151  ExpectLogContainsSomewhere(
2152      entries, pos,
2153      NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
2154      NetLog::PHASE_NONE);
2155
2156  const HttpResponseInfo* response = trans->GetResponseInfo();
2157  ASSERT_TRUE(response != NULL);
2158  ASSERT_FALSE(response->headers.get() == NULL);
2159  EXPECT_TRUE(response->headers->IsKeepAlive());
2160  EXPECT_EQ(407, response->headers->response_code());
2161  EXPECT_EQ(10, response->headers->GetContentLength());
2162  EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2163  EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2164
2165  TestCompletionCallback callback2;
2166
2167  // Wrong password (should be "bar").
2168  rv = trans->RestartWithAuth(
2169      AuthCredentials(kFoo, kBaz), callback2.callback());
2170  EXPECT_EQ(ERR_IO_PENDING, rv);
2171
2172  rv = callback2.WaitForResult();
2173  EXPECT_EQ(OK, rv);
2174
2175  response = trans->GetResponseInfo();
2176  ASSERT_TRUE(response != NULL);
2177  ASSERT_FALSE(response->headers.get() == NULL);
2178  EXPECT_TRUE(response->headers->IsKeepAlive());
2179  EXPECT_EQ(407, response->headers->response_code());
2180  EXPECT_EQ(10, response->headers->GetContentLength());
2181  EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2182  EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2183
2184  // Flush the idle socket before the NetLog and HttpNetworkTransaction go
2185  // out of scope.
2186  session->CloseAllConnections();
2187}
2188
2189// Test that we don't read the response body when we fail to establish a tunnel,
2190// even if the user cancels the proxy's auth attempt.
2191TEST_P(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
2192  HttpRequestInfo request;
2193  request.method = "GET";
2194  request.url = GURL("https://www.google.com/");
2195  request.load_flags = 0;
2196
2197  // Configure against proxy server "myproxy:70".
2198  session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
2199
2200  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2201
2202  scoped_ptr<HttpTransaction> trans(
2203      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2204
2205  // Since we have proxy, should try to establish tunnel.
2206  MockWrite data_writes[] = {
2207    MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2208              "Host: www.google.com\r\n"
2209              "Proxy-Connection: keep-alive\r\n\r\n"),
2210  };
2211
2212  // The proxy responds to the connect with a 407.
2213  MockRead data_reads[] = {
2214    MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2215    MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2216    MockRead("Content-Length: 10\r\n\r\n"),
2217    MockRead(SYNCHRONOUS, ERR_UNEXPECTED),  // Should not be reached.
2218  };
2219
2220  StaticSocketDataProvider data(data_reads, arraysize(data_reads),
2221                                data_writes, arraysize(data_writes));
2222  session_deps_.socket_factory->AddSocketDataProvider(&data);
2223
2224  TestCompletionCallback callback;
2225
2226  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
2227  EXPECT_EQ(ERR_IO_PENDING, rv);
2228
2229  rv = callback.WaitForResult();
2230  EXPECT_EQ(OK, rv);
2231
2232  const HttpResponseInfo* response = trans->GetResponseInfo();
2233  ASSERT_TRUE(response != NULL);
2234
2235  EXPECT_TRUE(response->headers->IsKeepAlive());
2236  EXPECT_EQ(407, response->headers->response_code());
2237  EXPECT_EQ(10, response->headers->GetContentLength());
2238  EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2239
2240  std::string response_data;
2241  rv = ReadTransaction(trans.get(), &response_data);
2242  EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
2243
2244  // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
2245  session->CloseAllConnections();
2246}
2247
2248// Test when a server (non-proxy) returns a 407 (proxy-authenticate).
2249// The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
2250TEST_P(HttpNetworkTransactionTest, UnexpectedProxyAuth) {
2251  HttpRequestInfo request;
2252  request.method = "GET";
2253  request.url = GURL("http://www.google.com/");
2254  request.load_flags = 0;
2255
2256  // We are using a DIRECT connection (i.e. no proxy) for this session.
2257  scoped_ptr<HttpTransaction> trans(
2258      new HttpNetworkTransaction(DEFAULT_PRIORITY,
2259                                 CreateSession(&session_deps_)));
2260
2261  MockWrite data_writes1[] = {
2262    MockWrite("GET / HTTP/1.1\r\n"
2263              "Host: www.google.com\r\n"
2264              "Connection: keep-alive\r\n\r\n"),
2265  };
2266
2267  MockRead data_reads1[] = {
2268    MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
2269    MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2270    // Large content-length -- won't matter, as connection will be reset.
2271    MockRead("Content-Length: 10000\r\n\r\n"),
2272    MockRead(SYNCHRONOUS, ERR_FAILED),
2273  };
2274
2275  StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2276                                 data_writes1, arraysize(data_writes1));
2277  session_deps_.socket_factory->AddSocketDataProvider(&data1);
2278
2279  TestCompletionCallback callback;
2280
2281  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
2282  EXPECT_EQ(ERR_IO_PENDING, rv);
2283
2284  rv = callback.WaitForResult();
2285  EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
2286}
2287
2288// Tests when an HTTPS server (non-proxy) returns a 407 (proxy-authentication)
2289// through a non-authenticating proxy. The request should fail with
2290// ERR_UNEXPECTED_PROXY_AUTH.
2291// Note that it is impossible to detect if an HTTP server returns a 407 through
2292// a non-authenticating proxy - there is nothing to indicate whether the
2293// response came from the proxy or the server, so it is treated as if the proxy
2294// issued the challenge.
2295TEST_P(HttpNetworkTransactionTest,
2296       HttpsServerRequestsProxyAuthThroughProxy) {
2297  HttpRequestInfo request;
2298  request.method = "GET";
2299  request.url = GURL("https://www.google.com/");
2300
2301  session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
2302  CapturingBoundNetLog log;
2303  session_deps_.net_log = log.bound().net_log();
2304  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2305
2306  // Since we have proxy, should try to establish tunnel.
2307  MockWrite data_writes1[] = {
2308    MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2309              "Host: www.google.com\r\n"
2310              "Proxy-Connection: keep-alive\r\n\r\n"),
2311
2312    MockWrite("GET / HTTP/1.1\r\n"
2313              "Host: www.google.com\r\n"
2314              "Connection: keep-alive\r\n\r\n"),
2315  };
2316
2317  MockRead data_reads1[] = {
2318    MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2319
2320    MockRead("HTTP/1.1 407 Unauthorized\r\n"),
2321    MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2322    MockRead("\r\n"),
2323    MockRead(SYNCHRONOUS, OK),
2324  };
2325
2326  StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2327                                 data_writes1, arraysize(data_writes1));
2328  session_deps_.socket_factory->AddSocketDataProvider(&data1);
2329  SSLSocketDataProvider ssl(ASYNC, OK);
2330  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2331
2332  TestCompletionCallback callback1;
2333
2334  scoped_ptr<HttpTransaction> trans(
2335      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2336
2337  int rv = trans->Start(&request, callback1.callback(), log.bound());
2338  EXPECT_EQ(ERR_IO_PENDING, rv);
2339
2340  rv = callback1.WaitForResult();
2341  EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
2342  net::CapturingNetLog::CapturedEntryList entries;
2343  log.GetEntries(&entries);
2344  size_t pos = ExpectLogContainsSomewhere(
2345      entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
2346      NetLog::PHASE_NONE);
2347  ExpectLogContainsSomewhere(
2348      entries, pos,
2349      NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
2350      NetLog::PHASE_NONE);
2351}
2352
2353// Test the load timing for HTTPS requests with an HTTP proxy.
2354TEST_P(HttpNetworkTransactionTest, HttpProxyLoadTimingNoPacTwoRequests) {
2355  HttpRequestInfo request1;
2356  request1.method = "GET";
2357  request1.url = GURL("https://www.google.com/1");
2358
2359  HttpRequestInfo request2;
2360  request2.method = "GET";
2361  request2.url = GURL("https://www.google.com/2");
2362
2363  // Configure against proxy server "myproxy:70".
2364  session_deps_.proxy_service.reset(
2365      ProxyService::CreateFixed("PROXY myproxy:70"));
2366  CapturingBoundNetLog log;
2367  session_deps_.net_log = log.bound().net_log();
2368  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2369
2370  // Since we have proxy, should try to establish tunnel.
2371  MockWrite data_writes1[] = {
2372    MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2373              "Host: www.google.com\r\n"
2374              "Proxy-Connection: keep-alive\r\n\r\n"),
2375
2376    MockWrite("GET /1 HTTP/1.1\r\n"
2377              "Host: www.google.com\r\n"
2378              "Connection: keep-alive\r\n\r\n"),
2379
2380    MockWrite("GET /2 HTTP/1.1\r\n"
2381              "Host: www.google.com\r\n"
2382              "Connection: keep-alive\r\n\r\n"),
2383  };
2384
2385  // The proxy responds to the connect with a 407, using a persistent
2386  // connection.
2387  MockRead data_reads1[] = {
2388    MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2389
2390    MockRead("HTTP/1.1 200 OK\r\n"),
2391    MockRead("Content-Length: 1\r\n\r\n"),
2392    MockRead(SYNCHRONOUS, "1"),
2393
2394    MockRead("HTTP/1.1 200 OK\r\n"),
2395    MockRead("Content-Length: 2\r\n\r\n"),
2396    MockRead(SYNCHRONOUS, "22"),
2397  };
2398
2399  StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2400                                 data_writes1, arraysize(data_writes1));
2401  session_deps_.socket_factory->AddSocketDataProvider(&data1);
2402  SSLSocketDataProvider ssl(ASYNC, OK);
2403  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2404
2405  TestCompletionCallback callback1;
2406  scoped_ptr<HttpTransaction> trans1(
2407      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2408
2409  int rv = trans1->Start(&request1, callback1.callback(), log.bound());
2410  EXPECT_EQ(ERR_IO_PENDING, rv);
2411
2412  rv = callback1.WaitForResult();
2413  EXPECT_EQ(OK, rv);
2414
2415  const HttpResponseInfo* response1 = trans1->GetResponseInfo();
2416  ASSERT_TRUE(response1 != NULL);
2417  ASSERT_TRUE(response1->headers.get() != NULL);
2418  EXPECT_EQ(1, response1->headers->GetContentLength());
2419
2420  LoadTimingInfo load_timing_info1;
2421  EXPECT_TRUE(trans1->GetLoadTimingInfo(&load_timing_info1));
2422  TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_SSL_TIMES);
2423
2424  trans1.reset();
2425
2426  TestCompletionCallback callback2;
2427  scoped_ptr<HttpTransaction> trans2(
2428      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2429
2430  rv = trans2->Start(&request2, callback2.callback(), log.bound());
2431  EXPECT_EQ(ERR_IO_PENDING, rv);
2432
2433  rv = callback2.WaitForResult();
2434  EXPECT_EQ(OK, rv);
2435
2436  const HttpResponseInfo* response2 = trans2->GetResponseInfo();
2437  ASSERT_TRUE(response2 != NULL);
2438  ASSERT_TRUE(response2->headers.get() != NULL);
2439  EXPECT_EQ(2, response2->headers->GetContentLength());
2440
2441  LoadTimingInfo load_timing_info2;
2442  EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
2443  TestLoadTimingReused(load_timing_info2);
2444
2445  EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
2446
2447  trans2.reset();
2448  session->CloseAllConnections();
2449}
2450
2451// Test the load timing for HTTPS requests with an HTTP proxy and a PAC script.
2452TEST_P(HttpNetworkTransactionTest, HttpProxyLoadTimingWithPacTwoRequests) {
2453  HttpRequestInfo request1;
2454  request1.method = "GET";
2455  request1.url = GURL("https://www.google.com/1");
2456
2457  HttpRequestInfo request2;
2458  request2.method = "GET";
2459  request2.url = GURL("https://www.google.com/2");
2460
2461  // Configure against proxy server "myproxy:70".
2462  session_deps_.proxy_service.reset(
2463      ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
2464  CapturingBoundNetLog log;
2465  session_deps_.net_log = log.bound().net_log();
2466  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2467
2468  // Since we have proxy, should try to establish tunnel.
2469  MockWrite data_writes1[] = {
2470    MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2471              "Host: www.google.com\r\n"
2472              "Proxy-Connection: keep-alive\r\n\r\n"),
2473
2474    MockWrite("GET /1 HTTP/1.1\r\n"
2475              "Host: www.google.com\r\n"
2476              "Connection: keep-alive\r\n\r\n"),
2477
2478    MockWrite("GET /2 HTTP/1.1\r\n"
2479              "Host: www.google.com\r\n"
2480              "Connection: keep-alive\r\n\r\n"),
2481  };
2482
2483  // The proxy responds to the connect with a 407, using a persistent
2484  // connection.
2485  MockRead data_reads1[] = {
2486    MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2487
2488    MockRead("HTTP/1.1 200 OK\r\n"),
2489    MockRead("Content-Length: 1\r\n\r\n"),
2490    MockRead(SYNCHRONOUS, "1"),
2491
2492    MockRead("HTTP/1.1 200 OK\r\n"),
2493    MockRead("Content-Length: 2\r\n\r\n"),
2494    MockRead(SYNCHRONOUS, "22"),
2495  };
2496
2497  StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2498                                 data_writes1, arraysize(data_writes1));
2499  session_deps_.socket_factory->AddSocketDataProvider(&data1);
2500  SSLSocketDataProvider ssl(ASYNC, OK);
2501  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2502
2503  TestCompletionCallback callback1;
2504  scoped_ptr<HttpTransaction> trans1(
2505      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2506
2507  int rv = trans1->Start(&request1, callback1.callback(), log.bound());
2508  EXPECT_EQ(ERR_IO_PENDING, rv);
2509
2510  rv = callback1.WaitForResult();
2511  EXPECT_EQ(OK, rv);
2512
2513  const HttpResponseInfo* response1 = trans1->GetResponseInfo();
2514  ASSERT_TRUE(response1 != NULL);
2515  ASSERT_TRUE(response1->headers.get() != NULL);
2516  EXPECT_EQ(1, response1->headers->GetContentLength());
2517
2518  LoadTimingInfo load_timing_info1;
2519  EXPECT_TRUE(trans1->GetLoadTimingInfo(&load_timing_info1));
2520  TestLoadTimingNotReusedWithPac(load_timing_info1,
2521                                 CONNECT_TIMING_HAS_SSL_TIMES);
2522
2523  trans1.reset();
2524
2525  TestCompletionCallback callback2;
2526  scoped_ptr<HttpTransaction> trans2(
2527      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2528
2529  rv = trans2->Start(&request2, callback2.callback(), log.bound());
2530  EXPECT_EQ(ERR_IO_PENDING, rv);
2531
2532  rv = callback2.WaitForResult();
2533  EXPECT_EQ(OK, rv);
2534
2535  const HttpResponseInfo* response2 = trans2->GetResponseInfo();
2536  ASSERT_TRUE(response2 != NULL);
2537  ASSERT_TRUE(response2->headers.get() != NULL);
2538  EXPECT_EQ(2, response2->headers->GetContentLength());
2539
2540  LoadTimingInfo load_timing_info2;
2541  EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
2542  TestLoadTimingReusedWithPac(load_timing_info2);
2543
2544  EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
2545
2546  trans2.reset();
2547  session->CloseAllConnections();
2548}
2549
2550// Test a simple get through an HTTPS Proxy.
2551TEST_P(HttpNetworkTransactionTest, HttpsProxyGet) {
2552  HttpRequestInfo request;
2553  request.method = "GET";
2554  request.url = GURL("http://www.google.com/");
2555
2556  // Configure against https proxy server "proxy:70".
2557  session_deps_.proxy_service.reset(ProxyService::CreateFixed(
2558      "https://proxy:70"));
2559  CapturingBoundNetLog log;
2560  session_deps_.net_log = log.bound().net_log();
2561  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2562
2563  // Since we have proxy, should use full url
2564  MockWrite data_writes1[] = {
2565    MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2566              "Host: www.google.com\r\n"
2567              "Proxy-Connection: keep-alive\r\n\r\n"),
2568  };
2569
2570  MockRead data_reads1[] = {
2571    MockRead("HTTP/1.1 200 OK\r\n"),
2572    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2573    MockRead("Content-Length: 100\r\n\r\n"),
2574    MockRead(SYNCHRONOUS, OK),
2575  };
2576
2577  StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2578                                 data_writes1, arraysize(data_writes1));
2579  session_deps_.socket_factory->AddSocketDataProvider(&data1);
2580  SSLSocketDataProvider ssl(ASYNC, OK);
2581  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2582
2583  TestCompletionCallback callback1;
2584
2585  scoped_ptr<HttpTransaction> trans(
2586      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2587
2588  int rv = trans->Start(&request, callback1.callback(), log.bound());
2589  EXPECT_EQ(ERR_IO_PENDING, rv);
2590
2591  rv = callback1.WaitForResult();
2592  EXPECT_EQ(OK, rv);
2593
2594  LoadTimingInfo load_timing_info;
2595  EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
2596  TestLoadTimingNotReused(load_timing_info,
2597                          CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
2598
2599  const HttpResponseInfo* response = trans->GetResponseInfo();
2600  ASSERT_TRUE(response != NULL);
2601
2602  EXPECT_TRUE(response->headers->IsKeepAlive());
2603  EXPECT_EQ(200, response->headers->response_code());
2604  EXPECT_EQ(100, response->headers->GetContentLength());
2605  EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2606
2607  // The password prompt info should not be set.
2608  EXPECT_TRUE(response->auth_challenge.get() == NULL);
2609}
2610
2611// Test a SPDY get through an HTTPS Proxy.
2612TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGet) {
2613  HttpRequestInfo request;
2614  request.method = "GET";
2615  request.url = GURL("http://www.google.com/");
2616  request.load_flags = 0;
2617
2618  // Configure against https proxy server "proxy:70".
2619  session_deps_.proxy_service.reset(ProxyService::CreateFixed(
2620      "https://proxy:70"));
2621  CapturingBoundNetLog log;
2622  session_deps_.net_log = log.bound().net_log();
2623  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2624
2625  // fetch http://www.google.com/ via SPDY
2626  scoped_ptr<SpdyFrame> req(
2627      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
2628  MockWrite spdy_writes[] = { CreateMockWrite(*req) };
2629
2630  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2631  scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
2632  MockRead spdy_reads[] = {
2633    CreateMockRead(*resp),
2634    CreateMockRead(*data),
2635    MockRead(ASYNC, 0, 0),
2636  };
2637
2638  DelayedSocketData spdy_data(
2639      1,  // wait for one write to finish before reading.
2640      spdy_reads, arraysize(spdy_reads),
2641      spdy_writes, arraysize(spdy_writes));
2642  session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
2643
2644  SSLSocketDataProvider ssl(ASYNC, OK);
2645  ssl.SetNextProto(GetParam());
2646  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2647
2648  TestCompletionCallback callback1;
2649
2650  scoped_ptr<HttpTransaction> trans(
2651      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2652
2653  int rv = trans->Start(&request, callback1.callback(), log.bound());
2654  EXPECT_EQ(ERR_IO_PENDING, rv);
2655
2656  rv = callback1.WaitForResult();
2657  EXPECT_EQ(OK, rv);
2658
2659  LoadTimingInfo load_timing_info;
2660  EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
2661  TestLoadTimingNotReused(load_timing_info,
2662                          CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
2663
2664  const HttpResponseInfo* response = trans->GetResponseInfo();
2665  ASSERT_TRUE(response != NULL);
2666  ASSERT_TRUE(response->headers.get() != NULL);
2667  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2668
2669  std::string response_data;
2670  ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
2671  EXPECT_EQ(kUploadData, response_data);
2672}
2673
2674// Test a SPDY get through an HTTPS Proxy.
2675TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGetWithProxyAuth) {
2676  HttpRequestInfo request;
2677  request.method = "GET";
2678  request.url = GURL("http://www.google.com/");
2679  request.load_flags = 0;
2680
2681  // Configure against https proxy server "myproxy:70".
2682  session_deps_.proxy_service.reset(
2683      ProxyService::CreateFixed("https://myproxy:70"));
2684  CapturingBoundNetLog log;
2685  session_deps_.net_log = log.bound().net_log();
2686  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2687
2688  // The first request will be a bare GET, the second request will be a
2689  // GET with a Proxy-Authorization header.
2690  scoped_ptr<SpdyFrame> req_get(
2691      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
2692  const char* const kExtraAuthorizationHeaders[] = {
2693    "proxy-authorization", "Basic Zm9vOmJhcg=="
2694  };
2695  scoped_ptr<SpdyFrame> req_get_authorization(
2696      spdy_util_.ConstructSpdyGet(kExtraAuthorizationHeaders,
2697                                  arraysize(kExtraAuthorizationHeaders) / 2,
2698                                  false,
2699                                  3,
2700                                  LOWEST,
2701                                  false));
2702  MockWrite spdy_writes[] = {
2703    CreateMockWrite(*req_get, 1),
2704    CreateMockWrite(*req_get_authorization, 4),
2705  };
2706
2707  // The first response is a 407 proxy authentication challenge, and the second
2708  // response will be a 200 response since the second request includes a valid
2709  // Authorization header.
2710  const char* const kExtraAuthenticationHeaders[] = {
2711    "proxy-authenticate", "Basic realm=\"MyRealm1\""
2712  };
2713  scoped_ptr<SpdyFrame> resp_authentication(
2714      spdy_util_.ConstructSpdySynReplyError(
2715          "407 Proxy Authentication Required",
2716          kExtraAuthenticationHeaders, arraysize(kExtraAuthenticationHeaders)/2,
2717          1));
2718  scoped_ptr<SpdyFrame> body_authentication(
2719      spdy_util_.ConstructSpdyBodyFrame(1, true));
2720  scoped_ptr<SpdyFrame> resp_data(
2721      spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
2722  scoped_ptr<SpdyFrame> body_data(spdy_util_.ConstructSpdyBodyFrame(3, true));
2723  MockRead spdy_reads[] = {
2724    CreateMockRead(*resp_authentication, 2),
2725    CreateMockRead(*body_authentication, 3),
2726    CreateMockRead(*resp_data, 5),
2727    CreateMockRead(*body_data, 6),
2728    MockRead(ASYNC, 0, 7),
2729  };
2730
2731  OrderedSocketData data(
2732      spdy_reads, arraysize(spdy_reads),
2733      spdy_writes, arraysize(spdy_writes));
2734  session_deps_.socket_factory->AddSocketDataProvider(&data);
2735
2736  SSLSocketDataProvider ssl(ASYNC, OK);
2737  ssl.SetNextProto(GetParam());
2738  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2739
2740  TestCompletionCallback callback1;
2741
2742  scoped_ptr<HttpTransaction> trans(
2743      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2744
2745  int rv = trans->Start(&request, callback1.callback(), log.bound());
2746  EXPECT_EQ(ERR_IO_PENDING, rv);
2747
2748  rv = callback1.WaitForResult();
2749  EXPECT_EQ(OK, rv);
2750
2751  const HttpResponseInfo* const response = trans->GetResponseInfo();
2752
2753  ASSERT_TRUE(response != NULL);
2754  ASSERT_TRUE(response->headers.get() != NULL);
2755  EXPECT_EQ(407, response->headers->response_code());
2756  EXPECT_TRUE(response->was_fetched_via_spdy);
2757  EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2758
2759  TestCompletionCallback callback2;
2760
2761  rv = trans->RestartWithAuth(
2762      AuthCredentials(kFoo, kBar), callback2.callback());
2763  EXPECT_EQ(ERR_IO_PENDING, rv);
2764
2765  rv = callback2.WaitForResult();
2766  EXPECT_EQ(OK, rv);
2767
2768  const HttpResponseInfo* const response_restart = trans->GetResponseInfo();
2769
2770  ASSERT_TRUE(response_restart != NULL);
2771  ASSERT_TRUE(response_restart->headers.get() != NULL);
2772  EXPECT_EQ(200, response_restart->headers->response_code());
2773  // The password prompt info should not be set.
2774  EXPECT_TRUE(response_restart->auth_challenge.get() == NULL);
2775}
2776
2777// Test a SPDY CONNECT through an HTTPS Proxy to an HTTPS (non-SPDY) Server.
2778TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectHttps) {
2779  HttpRequestInfo request;
2780  request.method = "GET";
2781  request.url = GURL("https://www.google.com/");
2782  request.load_flags = 0;
2783
2784  // Configure against https proxy server "proxy:70".
2785  session_deps_.proxy_service.reset(ProxyService::CreateFixed(
2786      "https://proxy:70"));
2787  CapturingBoundNetLog log;
2788  session_deps_.net_log = log.bound().net_log();
2789  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2790
2791  scoped_ptr<HttpTransaction> trans(
2792      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2793
2794  // CONNECT to www.google.com:443 via SPDY
2795  scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(NULL, 0, 1));
2796  // fetch https://www.google.com/ via HTTP
2797
2798  const char get[] = "GET / HTTP/1.1\r\n"
2799    "Host: www.google.com\r\n"
2800    "Connection: keep-alive\r\n\r\n";
2801  scoped_ptr<SpdyFrame> wrapped_get(
2802      spdy_util_.ConstructSpdyBodyFrame(1, get, strlen(get), false));
2803  scoped_ptr<SpdyFrame> conn_resp(
2804      spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2805  const char resp[] = "HTTP/1.1 200 OK\r\n"
2806      "Content-Length: 10\r\n\r\n";
2807  scoped_ptr<SpdyFrame> wrapped_get_resp(
2808      spdy_util_.ConstructSpdyBodyFrame(1, resp, strlen(resp), false));
2809  scoped_ptr<SpdyFrame> wrapped_body(
2810      spdy_util_.ConstructSpdyBodyFrame(1, "1234567890", 10, false));
2811  scoped_ptr<SpdyFrame> window_update(
2812      spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp->size()));
2813
2814  MockWrite spdy_writes[] = {
2815      CreateMockWrite(*connect, 1),
2816      CreateMockWrite(*wrapped_get, 3),
2817      CreateMockWrite(*window_update, 5),
2818  };
2819
2820  MockRead spdy_reads[] = {
2821    CreateMockRead(*conn_resp, 2, ASYNC),
2822    CreateMockRead(*wrapped_get_resp, 4, ASYNC),
2823    CreateMockRead(*wrapped_body, 6, ASYNC),
2824    CreateMockRead(*wrapped_body, 7, ASYNC),
2825    MockRead(ASYNC, 0, 8),
2826  };
2827
2828  OrderedSocketData spdy_data(
2829      spdy_reads, arraysize(spdy_reads),
2830      spdy_writes, arraysize(spdy_writes));
2831  session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
2832
2833  SSLSocketDataProvider ssl(ASYNC, OK);
2834  ssl.SetNextProto(GetParam());
2835  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2836  SSLSocketDataProvider ssl2(ASYNC, OK);
2837  ssl2.was_npn_negotiated = false;
2838  ssl2.protocol_negotiated = kProtoUnknown;
2839  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
2840
2841  TestCompletionCallback callback1;
2842
2843  int rv = trans->Start(&request, callback1.callback(), log.bound());
2844  EXPECT_EQ(ERR_IO_PENDING, rv);
2845
2846  rv = callback1.WaitForResult();
2847  EXPECT_EQ(OK, rv);
2848
2849  LoadTimingInfo load_timing_info;
2850  EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
2851  TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
2852
2853  const HttpResponseInfo* response = trans->GetResponseInfo();
2854  ASSERT_TRUE(response != NULL);
2855  ASSERT_TRUE(response->headers.get() != NULL);
2856  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2857
2858  std::string response_data;
2859  ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
2860  EXPECT_EQ("1234567890", response_data);
2861}
2862
2863// Test a SPDY CONNECT through an HTTPS Proxy to a SPDY server.
2864TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectSpdy) {
2865  HttpRequestInfo request;
2866  request.method = "GET";
2867  request.url = GURL("https://www.google.com/");
2868  request.load_flags = 0;
2869
2870  // Configure against https proxy server "proxy:70".
2871  session_deps_.proxy_service.reset(ProxyService::CreateFixed(
2872      "https://proxy:70"));
2873  CapturingBoundNetLog log;
2874  session_deps_.net_log = log.bound().net_log();
2875  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2876
2877  scoped_ptr<HttpTransaction> trans(
2878      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2879
2880  // CONNECT to www.google.com:443 via SPDY
2881  scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(NULL, 0, 1));
2882  // fetch https://www.google.com/ via SPDY
2883  const char* const kMyUrl = "https://www.google.com/";
2884  scoped_ptr<SpdyFrame> get(
2885      spdy_util_.ConstructSpdyGet(kMyUrl, false, 1, LOWEST));
2886  scoped_ptr<SpdyFrame> wrapped_get(
2887      spdy_util_.ConstructWrappedSpdyFrame(get, 1));
2888  scoped_ptr<SpdyFrame> conn_resp(
2889      spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2890  scoped_ptr<SpdyFrame> get_resp(
2891      spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2892  scoped_ptr<SpdyFrame> wrapped_get_resp(
2893      spdy_util_.ConstructWrappedSpdyFrame(get_resp, 1));
2894  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
2895  scoped_ptr<SpdyFrame> wrapped_body(
2896      spdy_util_.ConstructWrappedSpdyFrame(body, 1));
2897  scoped_ptr<SpdyFrame> window_update_get_resp(
2898      spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp->size()));
2899  scoped_ptr<SpdyFrame> window_update_body(
2900      spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_body->size()));
2901
2902  MockWrite spdy_writes[] = {
2903      CreateMockWrite(*connect, 1),
2904      CreateMockWrite(*wrapped_get, 3),
2905      CreateMockWrite(*window_update_get_resp, 5),
2906      CreateMockWrite(*window_update_body, 7),
2907  };
2908
2909  MockRead spdy_reads[] = {
2910    CreateMockRead(*conn_resp, 2, ASYNC),
2911    CreateMockRead(*wrapped_get_resp, 4, ASYNC),
2912    CreateMockRead(*wrapped_body, 6, ASYNC),
2913    MockRead(ASYNC, 0, 8),
2914  };
2915
2916  OrderedSocketData spdy_data(
2917      spdy_reads, arraysize(spdy_reads),
2918      spdy_writes, arraysize(spdy_writes));
2919  session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
2920
2921  SSLSocketDataProvider ssl(ASYNC, OK);
2922  ssl.SetNextProto(GetParam());
2923  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2924  SSLSocketDataProvider ssl2(ASYNC, OK);
2925  ssl2.SetNextProto(GetParam());
2926  ssl2.protocol_negotiated = GetParam();
2927  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
2928
2929  TestCompletionCallback callback1;
2930
2931  int rv = trans->Start(&request, callback1.callback(), log.bound());
2932  EXPECT_EQ(ERR_IO_PENDING, rv);
2933
2934  rv = callback1.WaitForResult();
2935  EXPECT_EQ(OK, rv);
2936
2937  LoadTimingInfo load_timing_info;
2938  EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
2939  TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
2940
2941  const HttpResponseInfo* response = trans->GetResponseInfo();
2942  ASSERT_TRUE(response != NULL);
2943  ASSERT_TRUE(response->headers.get() != NULL);
2944  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2945
2946  std::string response_data;
2947  ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
2948  EXPECT_EQ(kUploadData, response_data);
2949}
2950
2951// Test a SPDY CONNECT failure through an HTTPS Proxy.
2952TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectFailure) {
2953  HttpRequestInfo request;
2954  request.method = "GET";
2955  request.url = GURL("https://www.google.com/");
2956  request.load_flags = 0;
2957
2958  // Configure against https proxy server "proxy:70".
2959  session_deps_.proxy_service.reset(ProxyService::CreateFixed(
2960      "https://proxy:70"));
2961  CapturingBoundNetLog log;
2962  session_deps_.net_log = log.bound().net_log();
2963  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2964
2965  scoped_ptr<HttpTransaction> trans(
2966      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2967
2968  // CONNECT to www.google.com:443 via SPDY
2969  scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(NULL, 0, 1));
2970  scoped_ptr<SpdyFrame> get(
2971      spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
2972
2973  MockWrite spdy_writes[] = {
2974      CreateMockWrite(*connect, 1),
2975      CreateMockWrite(*get, 3),
2976  };
2977
2978  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdySynReplyError(1));
2979  scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
2980  MockRead spdy_reads[] = {
2981    CreateMockRead(*resp, 2, ASYNC),
2982    MockRead(ASYNC, 0, 4),
2983  };
2984
2985  OrderedSocketData spdy_data(
2986      spdy_reads, arraysize(spdy_reads),
2987      spdy_writes, arraysize(spdy_writes));
2988  session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
2989
2990  SSLSocketDataProvider ssl(ASYNC, OK);
2991  ssl.SetNextProto(GetParam());
2992  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2993  SSLSocketDataProvider ssl2(ASYNC, OK);
2994  ssl2.SetNextProto(GetParam());
2995  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
2996
2997  TestCompletionCallback callback1;
2998
2999  int rv = trans->Start(&request, callback1.callback(), log.bound());
3000  EXPECT_EQ(ERR_IO_PENDING, rv);
3001
3002  rv = callback1.WaitForResult();
3003  EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
3004
3005  // TODO(ttuttle): Anything else to check here?
3006}
3007
3008// Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
3009// HTTPS Proxy to different servers.
3010TEST_P(HttpNetworkTransactionTest,
3011       HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsTwoServers) {
3012  // Configure against https proxy server "proxy:70".
3013  session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3014      "https://proxy:70"));
3015  CapturingBoundNetLog log;
3016  session_deps_.net_log = log.bound().net_log();
3017  scoped_refptr<HttpNetworkSession> session(
3018      SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
3019
3020  HttpRequestInfo request1;
3021  request1.method = "GET";
3022  request1.url = GURL("https://www.google.com/");
3023  request1.load_flags = 0;
3024
3025  HttpRequestInfo request2;
3026  request2.method = "GET";
3027  request2.url = GURL("https://news.google.com/");
3028  request2.load_flags = 0;
3029
3030  // CONNECT to www.google.com:443 via SPDY.
3031  scoped_ptr<SpdyFrame> connect1(spdy_util_.ConstructSpdyConnect(NULL, 0, 1));
3032  scoped_ptr<SpdyFrame> conn_resp1(
3033      spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3034
3035  // Fetch https://www.google.com/ via HTTP.
3036  const char get1[] = "GET / HTTP/1.1\r\n"
3037      "Host: www.google.com\r\n"
3038      "Connection: keep-alive\r\n\r\n";
3039  scoped_ptr<SpdyFrame> wrapped_get1(
3040      spdy_util_.ConstructSpdyBodyFrame(1, get1, strlen(get1), false));
3041  const char resp1[] = "HTTP/1.1 200 OK\r\n"
3042      "Content-Length: 1\r\n\r\n";
3043  scoped_ptr<SpdyFrame> wrapped_get_resp1(
3044      spdy_util_.ConstructSpdyBodyFrame(1, resp1, strlen(resp1), false));
3045  scoped_ptr<SpdyFrame> wrapped_body1(
3046      spdy_util_.ConstructSpdyBodyFrame(1, "1", 1, false));
3047  scoped_ptr<SpdyFrame> window_update(
3048      spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp1->size()));
3049
3050  // CONNECT to news.google.com:443 via SPDY.
3051  const char* const kConnectHeaders2[] = {
3052    spdy_util_.GetMethodKey(), "CONNECT",
3053    spdy_util_.GetPathKey(), "news.google.com:443",
3054    spdy_util_.GetHostKey(), "news.google.com",
3055    spdy_util_.GetVersionKey(), "HTTP/1.1",
3056  };
3057  scoped_ptr<SpdyFrame> connect2(
3058      spdy_util_.ConstructSpdyControlFrame(NULL,
3059                                           0,
3060                                           /*compressed*/ false,
3061                                           3,
3062                                           LOWEST,
3063                                           SYN_STREAM,
3064                                           CONTROL_FLAG_NONE,
3065                                           kConnectHeaders2,
3066                                           arraysize(kConnectHeaders2),
3067                                           0));
3068  scoped_ptr<SpdyFrame> conn_resp2(
3069      spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
3070
3071  // Fetch https://news.google.com/ via HTTP.
3072  const char get2[] = "GET / HTTP/1.1\r\n"
3073      "Host: news.google.com\r\n"
3074      "Connection: keep-alive\r\n\r\n";
3075  scoped_ptr<SpdyFrame> wrapped_get2(
3076      spdy_util_.ConstructSpdyBodyFrame(3, get2, strlen(get2), false));
3077  const char resp2[] = "HTTP/1.1 200 OK\r\n"
3078      "Content-Length: 2\r\n\r\n";
3079  scoped_ptr<SpdyFrame> wrapped_get_resp2(
3080      spdy_util_.ConstructSpdyBodyFrame(3, resp2, strlen(resp2), false));
3081  scoped_ptr<SpdyFrame> wrapped_body2(
3082      spdy_util_.ConstructSpdyBodyFrame(3, "22", 2, false));
3083
3084  MockWrite spdy_writes[] = {
3085      CreateMockWrite(*connect1, 0),
3086      CreateMockWrite(*wrapped_get1, 2),
3087      CreateMockWrite(*connect2, 5),
3088      CreateMockWrite(*wrapped_get2, 7),
3089  };
3090
3091  MockRead spdy_reads[] = {
3092    CreateMockRead(*conn_resp1, 1, ASYNC),
3093    CreateMockRead(*wrapped_get_resp1, 3, ASYNC),
3094    CreateMockRead(*wrapped_body1, 4, ASYNC),
3095    CreateMockRead(*conn_resp2, 6, ASYNC),
3096    CreateMockRead(*wrapped_get_resp2, 8, ASYNC),
3097    CreateMockRead(*wrapped_body2, 9, ASYNC),
3098    MockRead(ASYNC, 0, 10),
3099  };
3100
3101  DeterministicSocketData spdy_data(
3102      spdy_reads, arraysize(spdy_reads),
3103      spdy_writes, arraysize(spdy_writes));
3104  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&spdy_data);
3105
3106  SSLSocketDataProvider ssl(ASYNC, OK);
3107  ssl.SetNextProto(GetParam());
3108  session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
3109  SSLSocketDataProvider ssl2(ASYNC, OK);
3110  ssl2.was_npn_negotiated = false;
3111  ssl2.protocol_negotiated = kProtoUnknown;
3112  session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2);
3113  SSLSocketDataProvider ssl3(ASYNC, OK);
3114  ssl3.was_npn_negotiated = false;
3115  ssl3.protocol_negotiated = kProtoUnknown;
3116  session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl3);
3117
3118  TestCompletionCallback callback;
3119
3120  scoped_ptr<HttpTransaction> trans(
3121      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3122  int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
3123  EXPECT_EQ(ERR_IO_PENDING, rv);
3124  // The first connect and request, each of their responses, and the body.
3125  spdy_data.RunFor(5);
3126
3127  rv = callback.WaitForResult();
3128  EXPECT_EQ(OK, rv);
3129
3130  LoadTimingInfo load_timing_info;
3131  EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3132  TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
3133
3134  const HttpResponseInfo* response = trans->GetResponseInfo();
3135  ASSERT_TRUE(response != NULL);
3136  ASSERT_TRUE(response->headers.get() != NULL);
3137  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3138
3139  std::string response_data;
3140  scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(256));
3141  EXPECT_EQ(1, trans->Read(buf.get(), 256, callback.callback()));
3142
3143  scoped_ptr<HttpTransaction> trans2(
3144      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3145  rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
3146  EXPECT_EQ(ERR_IO_PENDING, rv);
3147
3148  // The second connect and request, each of their responses, and the body.
3149  spdy_data.RunFor(5);
3150  rv = callback.WaitForResult();
3151  EXPECT_EQ(OK, rv);
3152
3153  LoadTimingInfo load_timing_info2;
3154  EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
3155  // Even though the SPDY connection is reused, a new tunnelled connection has
3156  // to be created, so the socket's load timing looks like a fresh connection.
3157  TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_SSL_TIMES);
3158
3159  // The requests should have different IDs, since they each are using their own
3160  // separate stream.
3161  EXPECT_NE(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
3162
3163  EXPECT_EQ(2, trans2->Read(buf.get(), 256, callback.callback()));
3164}
3165
3166// Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
3167// HTTPS Proxy to the same server.
3168TEST_P(HttpNetworkTransactionTest,
3169       HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsSameServer) {
3170  // Configure against https proxy server "proxy:70".
3171  session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3172      "https://proxy:70"));
3173  CapturingBoundNetLog log;
3174  session_deps_.net_log = log.bound().net_log();
3175  scoped_refptr<HttpNetworkSession> session(
3176      SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
3177
3178  HttpRequestInfo request1;
3179  request1.method = "GET";
3180  request1.url = GURL("https://www.google.com/");
3181  request1.load_flags = 0;
3182
3183  HttpRequestInfo request2;
3184  request2.method = "GET";
3185  request2.url = GURL("https://www.google.com/2");
3186  request2.load_flags = 0;
3187
3188  // CONNECT to www.google.com:443 via SPDY.
3189  scoped_ptr<SpdyFrame> connect1(spdy_util_.ConstructSpdyConnect(NULL, 0, 1));
3190  scoped_ptr<SpdyFrame> conn_resp1(
3191      spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3192
3193  // Fetch https://www.google.com/ via HTTP.
3194  const char get1[] = "GET / HTTP/1.1\r\n"
3195      "Host: www.google.com\r\n"
3196      "Connection: keep-alive\r\n\r\n";
3197  scoped_ptr<SpdyFrame> wrapped_get1(
3198      spdy_util_.ConstructSpdyBodyFrame(1, get1, strlen(get1), false));
3199  const char resp1[] = "HTTP/1.1 200 OK\r\n"
3200      "Content-Length: 1\r\n\r\n";
3201  scoped_ptr<SpdyFrame> wrapped_get_resp1(
3202      spdy_util_.ConstructSpdyBodyFrame(1, resp1, strlen(resp1), false));
3203  scoped_ptr<SpdyFrame> wrapped_body1(
3204      spdy_util_.ConstructSpdyBodyFrame(1, "1", 1, false));
3205  scoped_ptr<SpdyFrame> window_update(
3206      spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp1->size()));
3207
3208  // Fetch https://www.google.com/2 via HTTP.
3209  const char get2[] = "GET /2 HTTP/1.1\r\n"
3210      "Host: www.google.com\r\n"
3211      "Connection: keep-alive\r\n\r\n";
3212  scoped_ptr<SpdyFrame> wrapped_get2(
3213      spdy_util_.ConstructSpdyBodyFrame(1, get2, strlen(get2), false));
3214  const char resp2[] = "HTTP/1.1 200 OK\r\n"
3215      "Content-Length: 2\r\n\r\n";
3216  scoped_ptr<SpdyFrame> wrapped_get_resp2(
3217      spdy_util_.ConstructSpdyBodyFrame(1, resp2, strlen(resp2), false));
3218  scoped_ptr<SpdyFrame> wrapped_body2(
3219      spdy_util_.ConstructSpdyBodyFrame(1, "22", 2, false));
3220
3221  MockWrite spdy_writes[] = {
3222      CreateMockWrite(*connect1, 0),
3223      CreateMockWrite(*wrapped_get1, 2),
3224      CreateMockWrite(*wrapped_get2, 5),
3225  };
3226
3227  MockRead spdy_reads[] = {
3228    CreateMockRead(*conn_resp1, 1, ASYNC),
3229    CreateMockRead(*wrapped_get_resp1, 3, ASYNC),
3230    CreateMockRead(*wrapped_body1, 4, ASYNC),
3231    CreateMockRead(*wrapped_get_resp2, 6, ASYNC),
3232    CreateMockRead(*wrapped_body2, 7, ASYNC),
3233    MockRead(ASYNC, 0, 8),
3234  };
3235
3236  DeterministicSocketData spdy_data(
3237      spdy_reads, arraysize(spdy_reads),
3238      spdy_writes, arraysize(spdy_writes));
3239  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&spdy_data);
3240
3241  SSLSocketDataProvider ssl(ASYNC, OK);
3242  ssl.SetNextProto(GetParam());
3243  session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
3244  SSLSocketDataProvider ssl2(ASYNC, OK);
3245  ssl2.was_npn_negotiated = false;
3246  ssl2.protocol_negotiated = kProtoUnknown;
3247  session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2);
3248
3249  TestCompletionCallback callback;
3250
3251  scoped_ptr<HttpTransaction> trans(
3252      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3253  int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
3254  EXPECT_EQ(ERR_IO_PENDING, rv);
3255  // The first connect and request, each of their responses, and the body.
3256  spdy_data.RunFor(5);
3257
3258  rv = callback.WaitForResult();
3259  EXPECT_EQ(OK, rv);
3260
3261  LoadTimingInfo load_timing_info;
3262  EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3263  TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
3264
3265  const HttpResponseInfo* response = trans->GetResponseInfo();
3266  ASSERT_TRUE(response != NULL);
3267  ASSERT_TRUE(response->headers.get() != NULL);
3268  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3269
3270  std::string response_data;
3271  scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(256));
3272  EXPECT_EQ(1, trans->Read(buf.get(), 256, callback.callback()));
3273  trans.reset();
3274
3275  scoped_ptr<HttpTransaction> trans2(
3276      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3277  rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
3278  EXPECT_EQ(ERR_IO_PENDING, rv);
3279
3280  // The second request, response, and body.  There should not be a second
3281  // connect.
3282  spdy_data.RunFor(3);
3283  rv = callback.WaitForResult();
3284  EXPECT_EQ(OK, rv);
3285
3286  LoadTimingInfo load_timing_info2;
3287  EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
3288  TestLoadTimingReused(load_timing_info2);
3289
3290  // The requests should have the same ID.
3291  EXPECT_EQ(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
3292
3293  EXPECT_EQ(2, trans2->Read(buf.get(), 256, callback.callback()));
3294}
3295
3296// Test load timing in the case of of two HTTP requests through a SPDY HTTPS
3297// Proxy to different servers.
3298TEST_P(HttpNetworkTransactionTest,
3299       HttpsProxySpdyLoadTimingTwoHttpRequests) {
3300  // Configure against https proxy server "proxy:70".
3301  session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3302      "https://proxy:70"));
3303  CapturingBoundNetLog log;
3304  session_deps_.net_log = log.bound().net_log();
3305  scoped_refptr<HttpNetworkSession> session(
3306      SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
3307
3308  HttpRequestInfo request1;
3309  request1.method = "GET";
3310  request1.url = GURL("http://www.google.com/");
3311  request1.load_flags = 0;
3312
3313  HttpRequestInfo request2;
3314  request2.method = "GET";
3315  request2.url = GURL("http://news.google.com/");
3316  request2.load_flags = 0;
3317
3318  // http://www.google.com/
3319  scoped_ptr<SpdyHeaderBlock> headers(
3320      spdy_util_.ConstructGetHeaderBlockForProxy("http://www.google.com/"));
3321  scoped_ptr<SpdyFrame> get1(spdy_util_.ConstructSpdyControlFrame(
3322      headers.Pass(), false, 1, LOWEST, SYN_STREAM, CONTROL_FLAG_FIN, 0));
3323  scoped_ptr<SpdyFrame> get_resp1(
3324      spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3325  scoped_ptr<SpdyFrame> body1(
3326      spdy_util_.ConstructSpdyBodyFrame(1, "1", 1, true));
3327
3328  // http://news.google.com/
3329  scoped_ptr<SpdyHeaderBlock> headers2(
3330      spdy_util_.ConstructGetHeaderBlockForProxy("http://news.google.com/"));
3331  scoped_ptr<SpdyFrame> get2(spdy_util_.ConstructSpdyControlFrame(
3332      headers2.Pass(), false, 3, LOWEST, SYN_STREAM, CONTROL_FLAG_FIN, 0));
3333  scoped_ptr<SpdyFrame> get_resp2(
3334      spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
3335  scoped_ptr<SpdyFrame> body2(
3336      spdy_util_.ConstructSpdyBodyFrame(3, "22", 2, true));
3337
3338  MockWrite spdy_writes[] = {
3339      CreateMockWrite(*get1, 0),
3340      CreateMockWrite(*get2, 3),
3341  };
3342
3343  MockRead spdy_reads[] = {
3344    CreateMockRead(*get_resp1, 1, ASYNC),
3345    CreateMockRead(*body1, 2, ASYNC),
3346    CreateMockRead(*get_resp2, 4, ASYNC),
3347    CreateMockRead(*body2, 5, ASYNC),
3348    MockRead(ASYNC, 0, 6),
3349  };
3350
3351  DeterministicSocketData spdy_data(
3352      spdy_reads, arraysize(spdy_reads),
3353      spdy_writes, arraysize(spdy_writes));
3354  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&spdy_data);
3355
3356  SSLSocketDataProvider ssl(ASYNC, OK);
3357  ssl.SetNextProto(GetParam());
3358  session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
3359
3360  TestCompletionCallback callback;
3361
3362  scoped_ptr<HttpTransaction> trans(
3363      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3364  int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
3365  EXPECT_EQ(ERR_IO_PENDING, rv);
3366  spdy_data.RunFor(2);
3367
3368  rv = callback.WaitForResult();
3369  EXPECT_EQ(OK, rv);
3370
3371  LoadTimingInfo load_timing_info;
3372  EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3373  TestLoadTimingNotReused(load_timing_info,
3374                          CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
3375
3376  const HttpResponseInfo* response = trans->GetResponseInfo();
3377  ASSERT_TRUE(response != NULL);
3378  ASSERT_TRUE(response->headers.get() != NULL);
3379  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3380
3381  std::string response_data;
3382  scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(256));
3383  EXPECT_EQ(ERR_IO_PENDING, trans->Read(buf.get(), 256, callback.callback()));
3384  spdy_data.RunFor(1);
3385  EXPECT_EQ(1, callback.WaitForResult());
3386  // Delete the first request, so the second one can reuse the socket.
3387  trans.reset();
3388
3389  scoped_ptr<HttpTransaction> trans2(
3390      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3391  rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
3392  EXPECT_EQ(ERR_IO_PENDING, rv);
3393
3394  spdy_data.RunFor(2);
3395  rv = callback.WaitForResult();
3396  EXPECT_EQ(OK, rv);
3397
3398  LoadTimingInfo load_timing_info2;
3399  EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
3400  TestLoadTimingReused(load_timing_info2);
3401
3402  // The requests should have the same ID.
3403  EXPECT_EQ(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
3404
3405  EXPECT_EQ(ERR_IO_PENDING, trans2->Read(buf.get(), 256, callback.callback()));
3406  spdy_data.RunFor(1);
3407  EXPECT_EQ(2, callback.WaitForResult());
3408}
3409
3410// Test the challenge-response-retry sequence through an HTTPS Proxy
3411TEST_P(HttpNetworkTransactionTest, HttpsProxyAuthRetry) {
3412  HttpRequestInfo request;
3413  request.method = "GET";
3414  request.url = GURL("http://www.google.com/");
3415  // when the no authentication data flag is set.
3416  request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
3417
3418  // Configure against https proxy server "myproxy:70".
3419  session_deps_.proxy_service.reset(
3420      ProxyService::CreateFixed("https://myproxy:70"));
3421  CapturingBoundNetLog log;
3422  session_deps_.net_log = log.bound().net_log();
3423  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3424
3425  // Since we have proxy, should use full url
3426  MockWrite data_writes1[] = {
3427    MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
3428              "Host: www.google.com\r\n"
3429              "Proxy-Connection: keep-alive\r\n\r\n"),
3430
3431    // After calling trans->RestartWithAuth(), this is the request we should
3432    // be issuing -- the final header line contains the credentials.
3433    MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
3434              "Host: www.google.com\r\n"
3435              "Proxy-Connection: keep-alive\r\n"
3436              "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3437  };
3438
3439  // The proxy responds to the GET with a 407, using a persistent
3440  // connection.
3441  MockRead data_reads1[] = {
3442    // No credentials.
3443    MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3444    MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3445    MockRead("Proxy-Connection: keep-alive\r\n"),
3446    MockRead("Content-Length: 0\r\n\r\n"),
3447
3448    MockRead("HTTP/1.1 200 OK\r\n"),
3449    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3450    MockRead("Content-Length: 100\r\n\r\n"),
3451    MockRead(SYNCHRONOUS, OK),
3452  };
3453
3454  StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3455                                 data_writes1, arraysize(data_writes1));
3456  session_deps_.socket_factory->AddSocketDataProvider(&data1);
3457  SSLSocketDataProvider ssl(ASYNC, OK);
3458  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3459
3460  TestCompletionCallback callback1;
3461
3462  scoped_ptr<HttpTransaction> trans(
3463      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3464
3465  int rv = trans->Start(&request, callback1.callback(), log.bound());
3466  EXPECT_EQ(ERR_IO_PENDING, rv);
3467
3468  rv = callback1.WaitForResult();
3469  EXPECT_EQ(OK, rv);
3470
3471  LoadTimingInfo load_timing_info;
3472  EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3473  TestLoadTimingNotReused(load_timing_info,
3474                          CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
3475
3476  const HttpResponseInfo* response = trans->GetResponseInfo();
3477  ASSERT_TRUE(response != NULL);
3478  ASSERT_FALSE(response->headers.get() == NULL);
3479  EXPECT_EQ(407, response->headers->response_code());
3480  EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3481  EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
3482
3483  TestCompletionCallback callback2;
3484
3485  rv = trans->RestartWithAuth(
3486      AuthCredentials(kFoo, kBar), callback2.callback());
3487  EXPECT_EQ(ERR_IO_PENDING, rv);
3488
3489  rv = callback2.WaitForResult();
3490  EXPECT_EQ(OK, rv);
3491
3492  load_timing_info = LoadTimingInfo();
3493  EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3494  // Retrying with HTTP AUTH is considered to be reusing a socket.
3495  TestLoadTimingReused(load_timing_info);
3496
3497  response = trans->GetResponseInfo();
3498  ASSERT_TRUE(response != NULL);
3499
3500  EXPECT_TRUE(response->headers->IsKeepAlive());
3501  EXPECT_EQ(200, response->headers->response_code());
3502  EXPECT_EQ(100, response->headers->GetContentLength());
3503  EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3504
3505  // The password prompt info should not be set.
3506  EXPECT_TRUE(response->auth_challenge.get() == NULL);
3507}
3508
3509void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
3510    const MockRead& status, int expected_status) {
3511  HttpRequestInfo request;
3512  request.method = "GET";
3513  request.url = GURL("https://www.google.com/");
3514  request.load_flags = 0;
3515
3516  // Configure against proxy server "myproxy:70".
3517  session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
3518
3519  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3520
3521  // Since we have proxy, should try to establish tunnel.
3522  MockWrite data_writes[] = {
3523    MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
3524              "Host: www.google.com\r\n"
3525              "Proxy-Connection: keep-alive\r\n\r\n"),
3526  };
3527
3528  MockRead data_reads[] = {
3529    status,
3530    MockRead("Content-Length: 10\r\n\r\n"),
3531    // No response body because the test stops reading here.
3532    MockRead(SYNCHRONOUS, ERR_UNEXPECTED),  // Should not be reached.
3533  };
3534
3535  StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3536                                data_writes, arraysize(data_writes));
3537  session_deps_.socket_factory->AddSocketDataProvider(&data);
3538
3539  TestCompletionCallback callback;
3540
3541  scoped_ptr<HttpTransaction> trans(
3542      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3543
3544  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
3545  EXPECT_EQ(ERR_IO_PENDING, rv);
3546
3547  rv = callback.WaitForResult();
3548  EXPECT_EQ(expected_status, rv);
3549}
3550
3551void HttpNetworkTransactionTest::ConnectStatusHelper(
3552    const MockRead& status) {
3553  ConnectStatusHelperWithExpectedStatus(
3554      status, ERR_TUNNEL_CONNECTION_FAILED);
3555}
3556
3557TEST_P(HttpNetworkTransactionTest, ConnectStatus100) {
3558  ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
3559}
3560
3561TEST_P(HttpNetworkTransactionTest, ConnectStatus101) {
3562  ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
3563}
3564
3565TEST_P(HttpNetworkTransactionTest, ConnectStatus201) {
3566  ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
3567}
3568
3569TEST_P(HttpNetworkTransactionTest, ConnectStatus202) {
3570  ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
3571}
3572
3573TEST_P(HttpNetworkTransactionTest, ConnectStatus203) {
3574  ConnectStatusHelper(
3575      MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
3576}
3577
3578TEST_P(HttpNetworkTransactionTest, ConnectStatus204) {
3579  ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
3580}
3581
3582TEST_P(HttpNetworkTransactionTest, ConnectStatus205) {
3583  ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
3584}
3585
3586TEST_P(HttpNetworkTransactionTest, ConnectStatus206) {
3587  ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
3588}
3589
3590TEST_P(HttpNetworkTransactionTest, ConnectStatus300) {
3591  ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
3592}
3593
3594TEST_P(HttpNetworkTransactionTest, ConnectStatus301) {
3595  ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
3596}
3597
3598TEST_P(HttpNetworkTransactionTest, ConnectStatus302) {
3599  ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
3600}
3601
3602TEST_P(HttpNetworkTransactionTest, ConnectStatus303) {
3603  ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
3604}
3605
3606TEST_P(HttpNetworkTransactionTest, ConnectStatus304) {
3607  ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
3608}
3609
3610TEST_P(HttpNetworkTransactionTest, ConnectStatus305) {
3611  ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
3612}
3613
3614TEST_P(HttpNetworkTransactionTest, ConnectStatus306) {
3615  ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
3616}
3617
3618TEST_P(HttpNetworkTransactionTest, ConnectStatus307) {
3619  ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
3620}
3621
3622TEST_P(HttpNetworkTransactionTest, ConnectStatus400) {
3623  ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
3624}
3625
3626TEST_P(HttpNetworkTransactionTest, ConnectStatus401) {
3627  ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
3628}
3629
3630TEST_P(HttpNetworkTransactionTest, ConnectStatus402) {
3631  ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
3632}
3633
3634TEST_P(HttpNetworkTransactionTest, ConnectStatus403) {
3635  ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
3636}
3637
3638TEST_P(HttpNetworkTransactionTest, ConnectStatus404) {
3639  ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
3640}
3641
3642TEST_P(HttpNetworkTransactionTest, ConnectStatus405) {
3643  ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
3644}
3645
3646TEST_P(HttpNetworkTransactionTest, ConnectStatus406) {
3647  ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
3648}
3649
3650TEST_P(HttpNetworkTransactionTest, ConnectStatus407) {
3651  ConnectStatusHelperWithExpectedStatus(
3652      MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3653      ERR_PROXY_AUTH_UNSUPPORTED);
3654}
3655
3656TEST_P(HttpNetworkTransactionTest, ConnectStatus408) {
3657  ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
3658}
3659
3660TEST_P(HttpNetworkTransactionTest, ConnectStatus409) {
3661  ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
3662}
3663
3664TEST_P(HttpNetworkTransactionTest, ConnectStatus410) {
3665  ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
3666}
3667
3668TEST_P(HttpNetworkTransactionTest, ConnectStatus411) {
3669  ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
3670}
3671
3672TEST_P(HttpNetworkTransactionTest, ConnectStatus412) {
3673  ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
3674}
3675
3676TEST_P(HttpNetworkTransactionTest, ConnectStatus413) {
3677  ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
3678}
3679
3680TEST_P(HttpNetworkTransactionTest, ConnectStatus414) {
3681  ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
3682}
3683
3684TEST_P(HttpNetworkTransactionTest, ConnectStatus415) {
3685  ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
3686}
3687
3688TEST_P(HttpNetworkTransactionTest, ConnectStatus416) {
3689  ConnectStatusHelper(
3690      MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
3691}
3692
3693TEST_P(HttpNetworkTransactionTest, ConnectStatus417) {
3694  ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
3695}
3696
3697TEST_P(HttpNetworkTransactionTest, ConnectStatus500) {
3698  ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
3699}
3700
3701TEST_P(HttpNetworkTransactionTest, ConnectStatus501) {
3702  ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
3703}
3704
3705TEST_P(HttpNetworkTransactionTest, ConnectStatus502) {
3706  ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
3707}
3708
3709TEST_P(HttpNetworkTransactionTest, ConnectStatus503) {
3710  ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
3711}
3712
3713TEST_P(HttpNetworkTransactionTest, ConnectStatus504) {
3714  ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
3715}
3716
3717TEST_P(HttpNetworkTransactionTest, ConnectStatus505) {
3718  ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
3719}
3720
3721// Test the flow when both the proxy server AND origin server require
3722// authentication. Again, this uses basic auth for both since that is
3723// the simplest to mock.
3724TEST_P(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
3725  HttpRequestInfo request;
3726  request.method = "GET";
3727  request.url = GURL("http://www.google.com/");
3728  request.load_flags = 0;
3729
3730  session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
3731
3732  // Configure against proxy server "myproxy:70".
3733  scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(DEFAULT_PRIORITY,
3734      CreateSession(&session_deps_)));
3735
3736  MockWrite data_writes1[] = {
3737    MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
3738              "Host: www.google.com\r\n"
3739              "Proxy-Connection: keep-alive\r\n\r\n"),
3740  };
3741
3742  MockRead data_reads1[] = {
3743    MockRead("HTTP/1.0 407 Unauthorized\r\n"),
3744    // Give a couple authenticate options (only the middle one is actually
3745    // supported).
3746    MockRead("Proxy-Authenticate: Basic invalid\r\n"),  // Malformed.
3747    MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3748    MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
3749    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3750    // Large content-length -- won't matter, as connection will be reset.
3751    MockRead("Content-Length: 10000\r\n\r\n"),
3752    MockRead(SYNCHRONOUS, ERR_FAILED),
3753  };
3754
3755  // After calling trans->RestartWithAuth() the first time, this is the
3756  // request we should be issuing -- the final header line contains the
3757  // proxy's credentials.
3758  MockWrite data_writes2[] = {
3759    MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
3760              "Host: www.google.com\r\n"
3761              "Proxy-Connection: keep-alive\r\n"
3762              "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3763  };
3764
3765  // Now the proxy server lets the request pass through to origin server.
3766  // The origin server responds with a 401.
3767  MockRead data_reads2[] = {
3768    MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3769    // Note: We are using the same realm-name as the proxy server. This is
3770    // completely valid, as realms are unique across hosts.
3771    MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3772    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3773    MockRead("Content-Length: 2000\r\n\r\n"),
3774    MockRead(SYNCHRONOUS, ERR_FAILED),  // Won't be reached.
3775  };
3776
3777  // After calling trans->RestartWithAuth() the second time, we should send
3778  // the credentials for both the proxy and origin server.
3779  MockWrite data_writes3[] = {
3780    MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
3781              "Host: www.google.com\r\n"
3782              "Proxy-Connection: keep-alive\r\n"
3783              "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
3784              "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
3785  };
3786
3787  // Lastly we get the desired content.
3788  MockRead data_reads3[] = {
3789    MockRead("HTTP/1.0 200 OK\r\n"),
3790    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3791    MockRead("Content-Length: 100\r\n\r\n"),
3792    MockRead(SYNCHRONOUS, OK),
3793  };
3794
3795  StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3796                                 data_writes1, arraysize(data_writes1));
3797  StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3798                                 data_writes2, arraysize(data_writes2));
3799  StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
3800                                 data_writes3, arraysize(data_writes3));
3801  session_deps_.socket_factory->AddSocketDataProvider(&data1);
3802  session_deps_.socket_factory->AddSocketDataProvider(&data2);
3803  session_deps_.socket_factory->AddSocketDataProvider(&data3);
3804
3805  TestCompletionCallback callback1;
3806
3807  int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
3808  EXPECT_EQ(ERR_IO_PENDING, rv);
3809
3810  rv = callback1.WaitForResult();
3811  EXPECT_EQ(OK, rv);
3812
3813  const HttpResponseInfo* response = trans->GetResponseInfo();
3814  ASSERT_TRUE(response != NULL);
3815  EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
3816
3817  TestCompletionCallback callback2;
3818
3819  rv = trans->RestartWithAuth(
3820      AuthCredentials(kFoo, kBar), callback2.callback());
3821  EXPECT_EQ(ERR_IO_PENDING, rv);
3822
3823  rv = callback2.WaitForResult();
3824  EXPECT_EQ(OK, rv);
3825
3826  response = trans->GetResponseInfo();
3827  ASSERT_TRUE(response != NULL);
3828  EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
3829
3830  TestCompletionCallback callback3;
3831
3832  rv = trans->RestartWithAuth(
3833      AuthCredentials(kFoo2, kBar2), callback3.callback());
3834  EXPECT_EQ(ERR_IO_PENDING, rv);
3835
3836  rv = callback3.WaitForResult();
3837  EXPECT_EQ(OK, rv);
3838
3839  response = trans->GetResponseInfo();
3840  EXPECT_TRUE(response->auth_challenge.get() == NULL);
3841  EXPECT_EQ(100, response->headers->GetContentLength());
3842}
3843
3844// For the NTLM implementation using SSPI, we skip the NTLM tests since we
3845// can't hook into its internals to cause it to generate predictable NTLM
3846// authorization headers.
3847#if defined(NTLM_PORTABLE)
3848// The NTLM authentication unit tests were generated by capturing the HTTP
3849// requests and responses using Fiddler 2 and inspecting the generated random
3850// bytes in the debugger.
3851
3852// Enter the correct password and authenticate successfully.
3853TEST_P(HttpNetworkTransactionTest, NTLMAuth1) {
3854  HttpRequestInfo request;
3855  request.method = "GET";
3856  request.url = GURL("http://172.22.68.17/kids/login.aspx");
3857  request.load_flags = 0;
3858
3859  HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom1,
3860                                                    MockGetHostName);
3861  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3862
3863  MockWrite data_writes1[] = {
3864    MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
3865              "Host: 172.22.68.17\r\n"
3866              "Connection: keep-alive\r\n\r\n"),
3867  };
3868
3869  MockRead data_reads1[] = {
3870    MockRead("HTTP/1.1 401 Access Denied\r\n"),
3871    // Negotiate and NTLM are often requested together.  However, we only want
3872    // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
3873    // the header that requests Negotiate for this test.
3874    MockRead("WWW-Authenticate: NTLM\r\n"),
3875    MockRead("Connection: close\r\n"),
3876    MockRead("Content-Length: 42\r\n"),
3877    MockRead("Content-Type: text/html\r\n\r\n"),
3878    // Missing content -- won't matter, as connection will be reset.
3879    MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
3880  };
3881
3882  MockWrite data_writes2[] = {
3883    // After restarting with a null identity, this is the
3884    // request we should be issuing -- the final header line contains a Type
3885    // 1 message.
3886    MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
3887              "Host: 172.22.68.17\r\n"
3888              "Connection: keep-alive\r\n"
3889              "Authorization: NTLM "
3890              "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
3891
3892    // After calling trans->RestartWithAuth(), we should send a Type 3 message
3893    // (the credentials for the origin server).  The second request continues
3894    // on the same connection.
3895    MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
3896              "Host: 172.22.68.17\r\n"
3897              "Connection: keep-alive\r\n"
3898              "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
3899              "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
3900              "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
3901              "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
3902              "ahlhx5I=\r\n\r\n"),
3903  };
3904
3905  MockRead data_reads2[] = {
3906    // The origin server responds with a Type 2 message.
3907    MockRead("HTTP/1.1 401 Access Denied\r\n"),
3908    MockRead("WWW-Authenticate: NTLM "
3909             "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
3910             "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
3911             "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
3912             "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
3913             "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
3914             "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
3915             "BtAAAAAAA=\r\n"),
3916    MockRead("Content-Length: 42\r\n"),
3917    MockRead("Content-Type: text/html\r\n\r\n"),
3918    MockRead("You are not authorized to view this page\r\n"),
3919
3920    // Lastly we get the desired content.
3921    MockRead("HTTP/1.1 200 OK\r\n"),
3922    MockRead("Content-Type: text/html; charset=utf-8\r\n"),
3923    MockRead("Content-Length: 13\r\n\r\n"),
3924    MockRead("Please Login\r\n"),
3925    MockRead(SYNCHRONOUS, OK),
3926  };
3927
3928  StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3929                                 data_writes1, arraysize(data_writes1));
3930  StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3931                                 data_writes2, arraysize(data_writes2));
3932  session_deps_.socket_factory->AddSocketDataProvider(&data1);
3933  session_deps_.socket_factory->AddSocketDataProvider(&data2);
3934
3935  TestCompletionCallback callback1;
3936
3937  scoped_ptr<HttpTransaction> trans(
3938      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3939
3940  int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
3941  EXPECT_EQ(ERR_IO_PENDING, rv);
3942
3943  rv = callback1.WaitForResult();
3944  EXPECT_EQ(OK, rv);
3945
3946  EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3947
3948  const HttpResponseInfo* response = trans->GetResponseInfo();
3949  ASSERT_FALSE(response == NULL);
3950  EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
3951
3952  TestCompletionCallback callback2;
3953
3954  rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kTestingNTLM),
3955                              callback2.callback());
3956  EXPECT_EQ(ERR_IO_PENDING, rv);
3957
3958  rv = callback2.WaitForResult();
3959  EXPECT_EQ(OK, rv);
3960
3961  EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3962
3963  response = trans->GetResponseInfo();
3964  ASSERT_TRUE(response != NULL);
3965  EXPECT_TRUE(response->auth_challenge.get() == NULL);
3966
3967  TestCompletionCallback callback3;
3968
3969  rv = trans->RestartWithAuth(AuthCredentials(), callback3.callback());
3970  EXPECT_EQ(ERR_IO_PENDING, rv);
3971
3972  rv = callback3.WaitForResult();
3973  EXPECT_EQ(OK, rv);
3974
3975  response = trans->GetResponseInfo();
3976  ASSERT_TRUE(response != NULL);
3977  EXPECT_TRUE(response->auth_challenge.get() == NULL);
3978  EXPECT_EQ(13, response->headers->GetContentLength());
3979}
3980
3981// Enter a wrong password, and then the correct one.
3982TEST_P(HttpNetworkTransactionTest, NTLMAuth2) {
3983  HttpRequestInfo request;
3984  request.method = "GET";
3985  request.url = GURL("http://172.22.68.17/kids/login.aspx");
3986  request.load_flags = 0;
3987
3988  HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom2,
3989                                                    MockGetHostName);
3990  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3991
3992  MockWrite data_writes1[] = {
3993    MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
3994              "Host: 172.22.68.17\r\n"
3995              "Connection: keep-alive\r\n\r\n"),
3996  };
3997
3998  MockRead data_reads1[] = {
3999    MockRead("HTTP/1.1 401 Access Denied\r\n"),
4000    // Negotiate and NTLM are often requested together.  However, we only want
4001    // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
4002    // the header that requests Negotiate for this test.
4003    MockRead("WWW-Authenticate: NTLM\r\n"),
4004    MockRead("Connection: close\r\n"),
4005    MockRead("Content-Length: 42\r\n"),
4006    MockRead("Content-Type: text/html\r\n\r\n"),
4007    // Missing content -- won't matter, as connection will be reset.
4008    MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
4009  };
4010
4011  MockWrite data_writes2[] = {
4012    // After restarting with a null identity, this is the
4013    // request we should be issuing -- the final header line contains a Type
4014    // 1 message.
4015    MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4016              "Host: 172.22.68.17\r\n"
4017              "Connection: keep-alive\r\n"
4018              "Authorization: NTLM "
4019              "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4020
4021    // After calling trans->RestartWithAuth(), we should send a Type 3 message
4022    // (the credentials for the origin server).  The second request continues
4023    // on the same connection.
4024    MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4025              "Host: 172.22.68.17\r\n"
4026              "Connection: keep-alive\r\n"
4027              "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4028              "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4029              "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
4030              "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
4031              "4Ww7b7E=\r\n\r\n"),
4032  };
4033
4034  MockRead data_reads2[] = {
4035    // The origin server responds with a Type 2 message.
4036    MockRead("HTTP/1.1 401 Access Denied\r\n"),
4037    MockRead("WWW-Authenticate: NTLM "
4038             "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
4039             "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4040             "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4041             "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4042             "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4043             "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4044             "BtAAAAAAA=\r\n"),
4045    MockRead("Content-Length: 42\r\n"),
4046    MockRead("Content-Type: text/html\r\n\r\n"),
4047    MockRead("You are not authorized to view this page\r\n"),
4048
4049    // Wrong password.
4050    MockRead("HTTP/1.1 401 Access Denied\r\n"),
4051    MockRead("WWW-Authenticate: NTLM\r\n"),
4052    MockRead("Connection: close\r\n"),
4053    MockRead("Content-Length: 42\r\n"),
4054    MockRead("Content-Type: text/html\r\n\r\n"),
4055    // Missing content -- won't matter, as connection will be reset.
4056    MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
4057  };
4058
4059  MockWrite data_writes3[] = {
4060    // After restarting with a null identity, this is the
4061    // request we should be issuing -- the final header line contains a Type
4062    // 1 message.
4063    MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4064              "Host: 172.22.68.17\r\n"
4065              "Connection: keep-alive\r\n"
4066              "Authorization: NTLM "
4067              "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4068
4069    // After calling trans->RestartWithAuth(), we should send a Type 3 message
4070    // (the credentials for the origin server).  The second request continues
4071    // on the same connection.
4072    MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4073              "Host: 172.22.68.17\r\n"
4074              "Connection: keep-alive\r\n"
4075              "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4076              "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4077              "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
4078              "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
4079              "+4MUm7c=\r\n\r\n"),
4080  };
4081
4082  MockRead data_reads3[] = {
4083    // The origin server responds with a Type 2 message.
4084    MockRead("HTTP/1.1 401 Access Denied\r\n"),
4085    MockRead("WWW-Authenticate: NTLM "
4086             "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
4087             "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4088             "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4089             "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4090             "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4091             "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4092             "BtAAAAAAA=\r\n"),
4093    MockRead("Content-Length: 42\r\n"),
4094    MockRead("Content-Type: text/html\r\n\r\n"),
4095    MockRead("You are not authorized to view this page\r\n"),
4096
4097    // Lastly we get the desired content.
4098    MockRead("HTTP/1.1 200 OK\r\n"),
4099    MockRead("Content-Type: text/html; charset=utf-8\r\n"),
4100    MockRead("Content-Length: 13\r\n\r\n"),
4101    MockRead("Please Login\r\n"),
4102    MockRead(SYNCHRONOUS, OK),
4103  };
4104
4105  StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4106                                 data_writes1, arraysize(data_writes1));
4107  StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4108                                 data_writes2, arraysize(data_writes2));
4109  StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
4110                                 data_writes3, arraysize(data_writes3));
4111  session_deps_.socket_factory->AddSocketDataProvider(&data1);
4112  session_deps_.socket_factory->AddSocketDataProvider(&data2);
4113  session_deps_.socket_factory->AddSocketDataProvider(&data3);
4114
4115  TestCompletionCallback callback1;
4116
4117  scoped_ptr<HttpTransaction> trans(
4118      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4119
4120  int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
4121  EXPECT_EQ(ERR_IO_PENDING, rv);
4122
4123  rv = callback1.WaitForResult();
4124  EXPECT_EQ(OK, rv);
4125
4126  EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4127
4128  const HttpResponseInfo* response = trans->GetResponseInfo();
4129  ASSERT_TRUE(response != NULL);
4130  EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
4131
4132  TestCompletionCallback callback2;
4133
4134  // Enter the wrong password.
4135  rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kWrongPassword),
4136                              callback2.callback());
4137  EXPECT_EQ(ERR_IO_PENDING, rv);
4138
4139  rv = callback2.WaitForResult();
4140  EXPECT_EQ(OK, rv);
4141
4142  EXPECT_TRUE(trans->IsReadyToRestartForAuth());
4143  TestCompletionCallback callback3;
4144  rv = trans->RestartWithAuth(AuthCredentials(), callback3.callback());
4145  EXPECT_EQ(ERR_IO_PENDING, rv);
4146  rv = callback3.WaitForResult();
4147  EXPECT_EQ(OK, rv);
4148  EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4149
4150  response = trans->GetResponseInfo();
4151  ASSERT_FALSE(response == NULL);
4152  EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
4153
4154  TestCompletionCallback callback4;
4155
4156  // Now enter the right password.
4157  rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kTestingNTLM),
4158                              callback4.callback());
4159  EXPECT_EQ(ERR_IO_PENDING, rv);
4160
4161  rv = callback4.WaitForResult();
4162  EXPECT_EQ(OK, rv);
4163
4164  EXPECT_TRUE(trans->IsReadyToRestartForAuth());
4165
4166  TestCompletionCallback callback5;
4167
4168  // One more roundtrip
4169  rv = trans->RestartWithAuth(AuthCredentials(), callback5.callback());
4170  EXPECT_EQ(ERR_IO_PENDING, rv);
4171
4172  rv = callback5.WaitForResult();
4173  EXPECT_EQ(OK, rv);
4174
4175  response = trans->GetResponseInfo();
4176  EXPECT_TRUE(response->auth_challenge.get() == NULL);
4177  EXPECT_EQ(13, response->headers->GetContentLength());
4178}
4179#endif  // NTLM_PORTABLE
4180
4181// Test reading a server response which has only headers, and no body.
4182// After some maximum number of bytes is consumed, the transaction should
4183// fail with ERR_RESPONSE_HEADERS_TOO_BIG.
4184TEST_P(HttpNetworkTransactionTest, LargeHeadersNoBody) {
4185  HttpRequestInfo request;
4186  request.method = "GET";
4187  request.url = GURL("http://www.google.com/");
4188  request.load_flags = 0;
4189
4190  scoped_ptr<HttpTransaction> trans(
4191      new HttpNetworkTransaction(DEFAULT_PRIORITY,
4192                                 CreateSession(&session_deps_)));
4193
4194  // Respond with 300 kb of headers (we should fail after 256 kb).
4195  std::string large_headers_string;
4196  FillLargeHeadersString(&large_headers_string, 300 * 1024);
4197
4198  MockRead data_reads[] = {
4199    MockRead("HTTP/1.0 200 OK\r\n"),
4200    MockRead(ASYNC, large_headers_string.data(), large_headers_string.size()),
4201    MockRead("\r\nBODY"),
4202    MockRead(SYNCHRONOUS, OK),
4203  };
4204  StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
4205  session_deps_.socket_factory->AddSocketDataProvider(&data);
4206
4207  TestCompletionCallback callback;
4208
4209  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
4210  EXPECT_EQ(ERR_IO_PENDING, rv);
4211
4212  rv = callback.WaitForResult();
4213  EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG, rv);
4214
4215  const HttpResponseInfo* response = trans->GetResponseInfo();
4216  EXPECT_TRUE(response == NULL);
4217}
4218
4219// Make sure that we don't try to reuse a TCPClientSocket when failing to
4220// establish tunnel.
4221// http://code.google.com/p/chromium/issues/detail?id=3772
4222TEST_P(HttpNetworkTransactionTest,
4223       DontRecycleTransportSocketForSSLTunnel) {
4224  HttpRequestInfo request;
4225  request.method = "GET";
4226  request.url = GURL("https://www.google.com/");
4227  request.load_flags = 0;
4228
4229  // Configure against proxy server "myproxy:70".
4230  session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
4231
4232  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4233
4234  scoped_ptr<HttpTransaction> trans(
4235      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4236
4237  // Since we have proxy, should try to establish tunnel.
4238  MockWrite data_writes1[] = {
4239    MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4240              "Host: www.google.com\r\n"
4241              "Proxy-Connection: keep-alive\r\n\r\n"),
4242  };
4243
4244  // The proxy responds to the connect with a 404, using a persistent
4245  // connection. Usually a proxy would return 501 (not implemented),
4246  // or 200 (tunnel established).
4247  MockRead data_reads1[] = {
4248    MockRead("HTTP/1.1 404 Not Found\r\n"),
4249    MockRead("Content-Length: 10\r\n\r\n"),
4250    MockRead(SYNCHRONOUS, ERR_UNEXPECTED),  // Should not be reached.
4251  };
4252
4253  StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4254                                 data_writes1, arraysize(data_writes1));
4255  session_deps_.socket_factory->AddSocketDataProvider(&data1);
4256
4257  TestCompletionCallback callback1;
4258
4259  int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
4260  EXPECT_EQ(ERR_IO_PENDING, rv);
4261
4262  rv = callback1.WaitForResult();
4263  EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
4264
4265  const HttpResponseInfo* response = trans->GetResponseInfo();
4266  EXPECT_TRUE(response == NULL);
4267
4268  // Empty the current queue.  This is necessary because idle sockets are
4269  // added to the connection pool asynchronously with a PostTask.
4270  base::MessageLoop::current()->RunUntilIdle();
4271
4272  // We now check to make sure the TCPClientSocket was not added back to
4273  // the pool.
4274  EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
4275  trans.reset();
4276  base::MessageLoop::current()->RunUntilIdle();
4277  // Make sure that the socket didn't get recycled after calling the destructor.
4278  EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
4279}
4280
4281// Make sure that we recycle a socket after reading all of the response body.
4282TEST_P(HttpNetworkTransactionTest, RecycleSocket) {
4283  HttpRequestInfo request;
4284  request.method = "GET";
4285  request.url = GURL("http://www.google.com/");
4286  request.load_flags = 0;
4287
4288  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4289
4290  scoped_ptr<HttpTransaction> trans(
4291      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4292
4293  MockRead data_reads[] = {
4294    // A part of the response body is received with the response headers.
4295    MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
4296    // The rest of the response body is received in two parts.
4297    MockRead("lo"),
4298    MockRead(" world"),
4299    MockRead("junk"),  // Should not be read!!
4300    MockRead(SYNCHRONOUS, OK),
4301  };
4302
4303  StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
4304  session_deps_.socket_factory->AddSocketDataProvider(&data);
4305
4306  TestCompletionCallback callback;
4307
4308  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
4309  EXPECT_EQ(ERR_IO_PENDING, rv);
4310
4311  rv = callback.WaitForResult();
4312  EXPECT_EQ(OK, rv);
4313
4314  const HttpResponseInfo* response = trans->GetResponseInfo();
4315  ASSERT_TRUE(response != NULL);
4316
4317  EXPECT_TRUE(response->headers.get() != NULL);
4318  std::string status_line = response->headers->GetStatusLine();
4319  EXPECT_EQ("HTTP/1.1 200 OK", status_line);
4320
4321  EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
4322
4323  std::string response_data;
4324  rv = ReadTransaction(trans.get(), &response_data);
4325  EXPECT_EQ(OK, rv);
4326  EXPECT_EQ("hello world", response_data);
4327
4328  // Empty the current queue.  This is necessary because idle sockets are
4329  // added to the connection pool asynchronously with a PostTask.
4330  base::MessageLoop::current()->RunUntilIdle();
4331
4332  // We now check to make sure the socket was added back to the pool.
4333  EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
4334}
4335
4336// Make sure that we recycle a SSL socket after reading all of the response
4337// body.
4338TEST_P(HttpNetworkTransactionTest, RecycleSSLSocket) {
4339  HttpRequestInfo request;
4340  request.method = "GET";
4341  request.url = GURL("https://www.google.com/");
4342  request.load_flags = 0;
4343
4344  MockWrite data_writes[] = {
4345    MockWrite("GET / HTTP/1.1\r\n"
4346              "Host: www.google.com\r\n"
4347              "Connection: keep-alive\r\n\r\n"),
4348  };
4349
4350  MockRead data_reads[] = {
4351    MockRead("HTTP/1.1 200 OK\r\n"),
4352    MockRead("Content-Length: 11\r\n\r\n"),
4353    MockRead("hello world"),
4354    MockRead(SYNCHRONOUS, OK),
4355  };
4356
4357  SSLSocketDataProvider ssl(ASYNC, OK);
4358  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
4359
4360  StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4361                                data_writes, arraysize(data_writes));
4362  session_deps_.socket_factory->AddSocketDataProvider(&data);
4363
4364  TestCompletionCallback callback;
4365
4366  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4367  scoped_ptr<HttpTransaction> trans(
4368      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4369
4370  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
4371
4372  EXPECT_EQ(ERR_IO_PENDING, rv);
4373  EXPECT_EQ(OK, callback.WaitForResult());
4374
4375  const HttpResponseInfo* response = trans->GetResponseInfo();
4376  ASSERT_TRUE(response != NULL);
4377  ASSERT_TRUE(response->headers.get() != NULL);
4378  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4379
4380  EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
4381
4382  std::string response_data;
4383  rv = ReadTransaction(trans.get(), &response_data);
4384  EXPECT_EQ(OK, rv);
4385  EXPECT_EQ("hello world", response_data);
4386
4387  // Empty the current queue.  This is necessary because idle sockets are
4388  // added to the connection pool asynchronously with a PostTask.
4389  base::MessageLoop::current()->RunUntilIdle();
4390
4391  // We now check to make sure the socket was added back to the pool.
4392  EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
4393}
4394
4395// Grab a SSL socket, use it, and put it back into the pool.  Then, reuse it
4396// from the pool and make sure that we recover okay.
4397TEST_P(HttpNetworkTransactionTest, RecycleDeadSSLSocket) {
4398  HttpRequestInfo request;
4399  request.method = "GET";
4400  request.url = GURL("https://www.google.com/");
4401  request.load_flags = 0;
4402
4403  MockWrite data_writes[] = {
4404    MockWrite("GET / HTTP/1.1\r\n"
4405              "Host: www.google.com\r\n"
4406              "Connection: keep-alive\r\n\r\n"),
4407    MockWrite("GET / HTTP/1.1\r\n"
4408              "Host: www.google.com\r\n"
4409              "Connection: keep-alive\r\n\r\n"),
4410  };
4411
4412  MockRead data_reads[] = {
4413    MockRead("HTTP/1.1 200 OK\r\n"),
4414    MockRead("Content-Length: 11\r\n\r\n"),
4415    MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
4416    MockRead("hello world"),
4417    MockRead(ASYNC, 0, 0)   // EOF
4418  };
4419
4420  SSLSocketDataProvider ssl(ASYNC, OK);
4421  SSLSocketDataProvider ssl2(ASYNC, OK);
4422  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
4423  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
4424
4425  StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4426                                data_writes, arraysize(data_writes));
4427  StaticSocketDataProvider data2(data_reads, arraysize(data_reads),
4428                                data_writes, arraysize(data_writes));
4429  session_deps_.socket_factory->AddSocketDataProvider(&data);
4430  session_deps_.socket_factory->AddSocketDataProvider(&data2);
4431
4432  TestCompletionCallback callback;
4433
4434  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4435  scoped_ptr<HttpTransaction> trans(
4436      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4437
4438  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
4439
4440  EXPECT_EQ(ERR_IO_PENDING, rv);
4441  EXPECT_EQ(OK, callback.WaitForResult());
4442
4443  const HttpResponseInfo* response = trans->GetResponseInfo();
4444  ASSERT_TRUE(response != NULL);
4445  ASSERT_TRUE(response->headers.get() != NULL);
4446  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4447
4448  EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
4449
4450  std::string response_data;
4451  rv = ReadTransaction(trans.get(), &response_data);
4452  EXPECT_EQ(OK, rv);
4453  EXPECT_EQ("hello world", response_data);
4454
4455  // Empty the current queue.  This is necessary because idle sockets are
4456  // added to the connection pool asynchronously with a PostTask.
4457  base::MessageLoop::current()->RunUntilIdle();
4458
4459  // We now check to make sure the socket was added back to the pool.
4460  EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
4461
4462  // Now start the second transaction, which should reuse the previous socket.
4463
4464  trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4465
4466  rv = trans->Start(&request, callback.callback(), BoundNetLog());
4467
4468  EXPECT_EQ(ERR_IO_PENDING, rv);
4469  EXPECT_EQ(OK, callback.WaitForResult());
4470
4471  response = trans->GetResponseInfo();
4472  ASSERT_TRUE(response != NULL);
4473  ASSERT_TRUE(response->headers.get() != NULL);
4474  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4475
4476  EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
4477
4478  rv = ReadTransaction(trans.get(), &response_data);
4479  EXPECT_EQ(OK, rv);
4480  EXPECT_EQ("hello world", response_data);
4481
4482  // Empty the current queue.  This is necessary because idle sockets are
4483  // added to the connection pool asynchronously with a PostTask.
4484  base::MessageLoop::current()->RunUntilIdle();
4485
4486  // We now check to make sure the socket was added back to the pool.
4487  EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
4488}
4489
4490// Make sure that we recycle a socket after a zero-length response.
4491// http://crbug.com/9880
4492TEST_P(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
4493  HttpRequestInfo request;
4494  request.method = "GET";
4495  request.url = GURL("http://www.google.com/csi?v=3&s=web&action=&"
4496                     "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
4497                     "e=17259,18167,19592,19773,19981,20133,20173,20233&"
4498                     "rt=prt.2642,ol.2649,xjs.2951");
4499  request.load_flags = 0;
4500
4501  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4502
4503  scoped_ptr<HttpTransaction> trans(
4504      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4505
4506  MockRead data_reads[] = {
4507    MockRead("HTTP/1.1 204 No Content\r\n"
4508             "Content-Length: 0\r\n"
4509             "Content-Type: text/html\r\n\r\n"),
4510    MockRead("junk"),  // Should not be read!!
4511    MockRead(SYNCHRONOUS, OK),
4512  };
4513
4514  StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
4515  session_deps_.socket_factory->AddSocketDataProvider(&data);
4516
4517  TestCompletionCallback callback;
4518
4519  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
4520  EXPECT_EQ(ERR_IO_PENDING, rv);
4521
4522  rv = callback.WaitForResult();
4523  EXPECT_EQ(OK, rv);
4524
4525  const HttpResponseInfo* response = trans->GetResponseInfo();
4526  ASSERT_TRUE(response != NULL);
4527
4528  EXPECT_TRUE(response->headers.get() != NULL);
4529  std::string status_line = response->headers->GetStatusLine();
4530  EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
4531
4532  EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
4533
4534  std::string response_data;
4535  rv = ReadTransaction(trans.get(), &response_data);
4536  EXPECT_EQ(OK, rv);
4537  EXPECT_EQ("", response_data);
4538
4539  // Empty the current queue.  This is necessary because idle sockets are
4540  // added to the connection pool asynchronously with a PostTask.
4541  base::MessageLoop::current()->RunUntilIdle();
4542
4543  // We now check to make sure the socket was added back to the pool.
4544  EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
4545}
4546
4547TEST_P(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
4548  ScopedVector<UploadElementReader> element_readers;
4549  element_readers.push_back(new UploadBytesElementReader("foo", 3));
4550  UploadDataStream upload_data_stream(&element_readers, 0);
4551
4552  HttpRequestInfo request[2];
4553  // Transaction 1: a GET request that succeeds.  The socket is recycled
4554  // after use.
4555  request[0].method = "GET";
4556  request[0].url = GURL("http://www.google.com/");
4557  request[0].load_flags = 0;
4558  // Transaction 2: a POST request.  Reuses the socket kept alive from
4559  // transaction 1.  The first attempts fails when writing the POST data.
4560  // This causes the transaction to retry with a new socket.  The second
4561  // attempt succeeds.
4562  request[1].method = "POST";
4563  request[1].url = GURL("http://www.google.com/login.cgi");
4564  request[1].upload_data_stream = &upload_data_stream;
4565  request[1].load_flags = 0;
4566
4567  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4568
4569  // The first socket is used for transaction 1 and the first attempt of
4570  // transaction 2.
4571
4572  // The response of transaction 1.
4573  MockRead data_reads1[] = {
4574    MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
4575    MockRead("hello world"),
4576    MockRead(SYNCHRONOUS, OK),
4577  };
4578  // The mock write results of transaction 1 and the first attempt of
4579  // transaction 2.
4580  MockWrite data_writes1[] = {
4581    MockWrite(SYNCHRONOUS, 64),  // GET
4582    MockWrite(SYNCHRONOUS, 93),  // POST
4583    MockWrite(SYNCHRONOUS, ERR_CONNECTION_ABORTED),  // POST data
4584  };
4585  StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4586                                 data_writes1, arraysize(data_writes1));
4587
4588  // The second socket is used for the second attempt of transaction 2.
4589
4590  // The response of transaction 2.
4591  MockRead data_reads2[] = {
4592    MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
4593    MockRead("welcome"),
4594    MockRead(SYNCHRONOUS, OK),
4595  };
4596  // The mock write results of the second attempt of transaction 2.
4597  MockWrite data_writes2[] = {
4598    MockWrite(SYNCHRONOUS, 93),  // POST
4599    MockWrite(SYNCHRONOUS, 3),  // POST data
4600  };
4601  StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4602                                 data_writes2, arraysize(data_writes2));
4603
4604  session_deps_.socket_factory->AddSocketDataProvider(&data1);
4605  session_deps_.socket_factory->AddSocketDataProvider(&data2);
4606
4607  const char* kExpectedResponseData[] = {
4608    "hello world", "welcome"
4609  };
4610
4611  for (int i = 0; i < 2; ++i) {
4612    scoped_ptr<HttpTransaction> trans(
4613        new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4614
4615    TestCompletionCallback callback;
4616
4617    int rv = trans->Start(&request[i], callback.callback(), BoundNetLog());
4618    EXPECT_EQ(ERR_IO_PENDING, rv);
4619
4620    rv = callback.WaitForResult();
4621    EXPECT_EQ(OK, rv);
4622
4623    const HttpResponseInfo* response = trans->GetResponseInfo();
4624    ASSERT_TRUE(response != NULL);
4625
4626    EXPECT_TRUE(response->headers.get() != NULL);
4627    EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4628
4629    std::string response_data;
4630    rv = ReadTransaction(trans.get(), &response_data);
4631    EXPECT_EQ(OK, rv);
4632    EXPECT_EQ(kExpectedResponseData[i], response_data);
4633  }
4634}
4635
4636// Test the request-challenge-retry sequence for basic auth when there is
4637// an identity in the URL. The request should be sent as normal, but when
4638// it fails the identity from the URL is used to answer the challenge.
4639TEST_P(HttpNetworkTransactionTest, AuthIdentityInURL) {
4640  HttpRequestInfo request;
4641  request.method = "GET";
4642  request.url = GURL("http://foo:b@r@www.google.com/");
4643  request.load_flags = LOAD_NORMAL;
4644
4645  scoped_ptr<HttpTransaction> trans(
4646      new HttpNetworkTransaction(DEFAULT_PRIORITY,
4647                                 CreateSession(&session_deps_)));
4648
4649  // The password contains an escaped character -- for this test to pass it
4650  // will need to be unescaped by HttpNetworkTransaction.
4651  EXPECT_EQ("b%40r", request.url.password());
4652
4653  MockWrite data_writes1[] = {
4654    MockWrite("GET / HTTP/1.1\r\n"
4655              "Host: www.google.com\r\n"
4656              "Connection: keep-alive\r\n\r\n"),
4657  };
4658
4659  MockRead data_reads1[] = {
4660    MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4661    MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4662    MockRead("Content-Length: 10\r\n\r\n"),
4663    MockRead(SYNCHRONOUS, ERR_FAILED),
4664  };
4665
4666  // After the challenge above, the transaction will be restarted using the
4667  // identity from the url (foo, b@r) to answer the challenge.
4668  MockWrite data_writes2[] = {
4669    MockWrite("GET / HTTP/1.1\r\n"
4670              "Host: www.google.com\r\n"
4671              "Connection: keep-alive\r\n"
4672              "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
4673  };
4674
4675  MockRead data_reads2[] = {
4676    MockRead("HTTP/1.0 200 OK\r\n"),
4677    MockRead("Content-Length: 100\r\n\r\n"),
4678    MockRead(SYNCHRONOUS, OK),
4679  };
4680
4681  StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4682                                 data_writes1, arraysize(data_writes1));
4683  StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4684                                 data_writes2, arraysize(data_writes2));
4685  session_deps_.socket_factory->AddSocketDataProvider(&data1);
4686  session_deps_.socket_factory->AddSocketDataProvider(&data2);
4687
4688  TestCompletionCallback callback1;
4689  int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
4690  EXPECT_EQ(ERR_IO_PENDING, rv);
4691  rv = callback1.WaitForResult();
4692  EXPECT_EQ(OK, rv);
4693  EXPECT_TRUE(trans->IsReadyToRestartForAuth());
4694
4695  TestCompletionCallback callback2;
4696  rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
4697  EXPECT_EQ(ERR_IO_PENDING, rv);
4698  rv = callback2.WaitForResult();
4699  EXPECT_EQ(OK, rv);
4700  EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4701
4702  const HttpResponseInfo* response = trans->GetResponseInfo();
4703  ASSERT_TRUE(response != NULL);
4704
4705  // There is no challenge info, since the identity in URL worked.
4706  EXPECT_TRUE(response->auth_challenge.get() == NULL);
4707
4708  EXPECT_EQ(100, response->headers->GetContentLength());
4709
4710  // Empty the current queue.
4711  base::MessageLoop::current()->RunUntilIdle();
4712}
4713
4714// Test the request-challenge-retry sequence for basic auth when there is an
4715// incorrect identity in the URL. The identity from the URL should be used only
4716// once.
4717TEST_P(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
4718  HttpRequestInfo request;
4719  request.method = "GET";
4720  // Note: the URL has a username:password in it.  The password "baz" is
4721  // wrong (should be "bar").
4722  request.url = GURL("http://foo:baz@www.google.com/");
4723
4724  request.load_flags = LOAD_NORMAL;
4725
4726  scoped_ptr<HttpTransaction> trans(
4727      new HttpNetworkTransaction(DEFAULT_PRIORITY,
4728                                 CreateSession(&session_deps_)));
4729
4730  MockWrite data_writes1[] = {
4731    MockWrite("GET / HTTP/1.1\r\n"
4732              "Host: www.google.com\r\n"
4733              "Connection: keep-alive\r\n\r\n"),
4734  };
4735
4736  MockRead data_reads1[] = {
4737    MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4738    MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4739    MockRead("Content-Length: 10\r\n\r\n"),
4740    MockRead(SYNCHRONOUS, ERR_FAILED),
4741  };
4742
4743  // After the challenge above, the transaction will be restarted using the
4744  // identity from the url (foo, baz) to answer the challenge.
4745  MockWrite data_writes2[] = {
4746    MockWrite("GET / HTTP/1.1\r\n"
4747              "Host: www.google.com\r\n"
4748              "Connection: keep-alive\r\n"
4749              "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
4750  };
4751
4752  MockRead data_reads2[] = {
4753    MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4754    MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4755    MockRead("Content-Length: 10\r\n\r\n"),
4756    MockRead(SYNCHRONOUS, ERR_FAILED),
4757  };
4758
4759  // After the challenge above, the transaction will be restarted using the
4760  // identity supplied by the user (foo, bar) to answer the challenge.
4761  MockWrite data_writes3[] = {
4762    MockWrite("GET / HTTP/1.1\r\n"
4763              "Host: www.google.com\r\n"
4764              "Connection: keep-alive\r\n"
4765              "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4766  };
4767
4768  MockRead data_reads3[] = {
4769    MockRead("HTTP/1.0 200 OK\r\n"),
4770    MockRead("Content-Length: 100\r\n\r\n"),
4771    MockRead(SYNCHRONOUS, OK),
4772  };
4773
4774  StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4775                                 data_writes1, arraysize(data_writes1));
4776  StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4777                                 data_writes2, arraysize(data_writes2));
4778  StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
4779                                 data_writes3, arraysize(data_writes3));
4780  session_deps_.socket_factory->AddSocketDataProvider(&data1);
4781  session_deps_.socket_factory->AddSocketDataProvider(&data2);
4782  session_deps_.socket_factory->AddSocketDataProvider(&data3);
4783
4784  TestCompletionCallback callback1;
4785
4786  int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
4787  EXPECT_EQ(ERR_IO_PENDING, rv);
4788
4789  rv = callback1.WaitForResult();
4790  EXPECT_EQ(OK, rv);
4791
4792  EXPECT_TRUE(trans->IsReadyToRestartForAuth());
4793  TestCompletionCallback callback2;
4794  rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
4795  EXPECT_EQ(ERR_IO_PENDING, rv);
4796  rv = callback2.WaitForResult();
4797  EXPECT_EQ(OK, rv);
4798  EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4799
4800  const HttpResponseInfo* response = trans->GetResponseInfo();
4801  ASSERT_TRUE(response != NULL);
4802  EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
4803
4804  TestCompletionCallback callback3;
4805  rv = trans->RestartWithAuth(
4806      AuthCredentials(kFoo, kBar), callback3.callback());
4807  EXPECT_EQ(ERR_IO_PENDING, rv);
4808  rv = callback3.WaitForResult();
4809  EXPECT_EQ(OK, rv);
4810  EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4811
4812  response = trans->GetResponseInfo();
4813  ASSERT_TRUE(response != NULL);
4814
4815  // There is no challenge info, since the identity worked.
4816  EXPECT_TRUE(response->auth_challenge.get() == NULL);
4817
4818  EXPECT_EQ(100, response->headers->GetContentLength());
4819
4820  // Empty the current queue.
4821  base::MessageLoop::current()->RunUntilIdle();
4822}
4823
4824// Test that previously tried username/passwords for a realm get re-used.
4825TEST_P(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
4826  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4827
4828  // Transaction 1: authenticate (foo, bar) on MyRealm1
4829  {
4830    HttpRequestInfo request;
4831    request.method = "GET";
4832    request.url = GURL("http://www.google.com/x/y/z");
4833    request.load_flags = 0;
4834
4835    scoped_ptr<HttpTransaction> trans(
4836        new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4837
4838    MockWrite data_writes1[] = {
4839      MockWrite("GET /x/y/z HTTP/1.1\r\n"
4840                "Host: www.google.com\r\n"
4841                "Connection: keep-alive\r\n\r\n"),
4842    };
4843
4844    MockRead data_reads1[] = {
4845      MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4846      MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4847      MockRead("Content-Length: 10000\r\n\r\n"),
4848      MockRead(SYNCHRONOUS, ERR_FAILED),
4849    };
4850
4851    // Resend with authorization (username=foo, password=bar)
4852    MockWrite data_writes2[] = {
4853      MockWrite("GET /x/y/z HTTP/1.1\r\n"
4854                "Host: www.google.com\r\n"
4855                "Connection: keep-alive\r\n"
4856                "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4857    };
4858
4859    // Sever accepts the authorization.
4860    MockRead data_reads2[] = {
4861      MockRead("HTTP/1.0 200 OK\r\n"),
4862      MockRead("Content-Length: 100\r\n\r\n"),
4863      MockRead(SYNCHRONOUS, OK),
4864    };
4865
4866    StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4867                                   data_writes1, arraysize(data_writes1));
4868    StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4869                                   data_writes2, arraysize(data_writes2));
4870    session_deps_.socket_factory->AddSocketDataProvider(&data1);
4871    session_deps_.socket_factory->AddSocketDataProvider(&data2);
4872
4873    TestCompletionCallback callback1;
4874
4875    int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
4876    EXPECT_EQ(ERR_IO_PENDING, rv);
4877
4878    rv = callback1.WaitForResult();
4879    EXPECT_EQ(OK, rv);
4880
4881    const HttpResponseInfo* response = trans->GetResponseInfo();
4882    ASSERT_TRUE(response != NULL);
4883    EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
4884
4885    TestCompletionCallback callback2;
4886
4887    rv = trans->RestartWithAuth(
4888        AuthCredentials(kFoo, kBar), callback2.callback());
4889    EXPECT_EQ(ERR_IO_PENDING, rv);
4890
4891    rv = callback2.WaitForResult();
4892    EXPECT_EQ(OK, rv);
4893
4894    response = trans->GetResponseInfo();
4895    ASSERT_TRUE(response != NULL);
4896    EXPECT_TRUE(response->auth_challenge.get() == NULL);
4897    EXPECT_EQ(100, response->headers->GetContentLength());
4898  }
4899
4900  // ------------------------------------------------------------------------
4901
4902  // Transaction 2: authenticate (foo2, bar2) on MyRealm2
4903  {
4904    HttpRequestInfo request;
4905    request.method = "GET";
4906    // Note that Transaction 1 was at /x/y/z, so this is in the same
4907    // protection space as MyRealm1.
4908    request.url = GURL("http://www.google.com/x/y/a/b");
4909    request.load_flags = 0;
4910
4911    scoped_ptr<HttpTransaction> trans(
4912        new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4913
4914    MockWrite data_writes1[] = {
4915      MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
4916                "Host: www.google.com\r\n"
4917                "Connection: keep-alive\r\n"
4918                // Send preemptive authorization for MyRealm1
4919                "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4920    };
4921
4922    // The server didn't like the preemptive authorization, and
4923    // challenges us for a different realm (MyRealm2).
4924    MockRead data_reads1[] = {
4925      MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4926      MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
4927      MockRead("Content-Length: 10000\r\n\r\n"),
4928      MockRead(SYNCHRONOUS, ERR_FAILED),
4929    };
4930
4931    // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
4932    MockWrite data_writes2[] = {
4933      MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
4934                "Host: www.google.com\r\n"
4935                "Connection: keep-alive\r\n"
4936                "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
4937    };
4938
4939    // Sever accepts the authorization.
4940    MockRead data_reads2[] = {
4941      MockRead("HTTP/1.0 200 OK\r\n"),
4942      MockRead("Content-Length: 100\r\n\r\n"),
4943      MockRead(SYNCHRONOUS, OK),
4944    };
4945
4946    StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4947                                   data_writes1, arraysize(data_writes1));
4948    StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4949                                   data_writes2, arraysize(data_writes2));
4950    session_deps_.socket_factory->AddSocketDataProvider(&data1);
4951    session_deps_.socket_factory->AddSocketDataProvider(&data2);
4952
4953    TestCompletionCallback callback1;
4954
4955    int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
4956    EXPECT_EQ(ERR_IO_PENDING, rv);
4957
4958    rv = callback1.WaitForResult();
4959    EXPECT_EQ(OK, rv);
4960
4961    const HttpResponseInfo* response = trans->GetResponseInfo();
4962    ASSERT_TRUE(response != NULL);
4963    ASSERT_TRUE(response->auth_challenge.get());
4964    EXPECT_FALSE(response->auth_challenge->is_proxy);
4965    EXPECT_EQ("www.google.com:80",
4966              response->auth_challenge->challenger.ToString());
4967    EXPECT_EQ("MyRealm2", response->auth_challenge->realm);
4968    EXPECT_EQ("basic", response->auth_challenge->scheme);
4969
4970    TestCompletionCallback callback2;
4971
4972    rv = trans->RestartWithAuth(
4973        AuthCredentials(kFoo2, kBar2), callback2.callback());
4974    EXPECT_EQ(ERR_IO_PENDING, rv);
4975
4976    rv = callback2.WaitForResult();
4977    EXPECT_EQ(OK, rv);
4978
4979    response = trans->GetResponseInfo();
4980    ASSERT_TRUE(response != NULL);
4981    EXPECT_TRUE(response->auth_challenge.get() == NULL);
4982    EXPECT_EQ(100, response->headers->GetContentLength());
4983  }
4984
4985  // ------------------------------------------------------------------------
4986
4987  // Transaction 3: Resend a request in MyRealm's protection space --
4988  // succeed with preemptive authorization.
4989  {
4990    HttpRequestInfo request;
4991    request.method = "GET";
4992    request.url = GURL("http://www.google.com/x/y/z2");
4993    request.load_flags = 0;
4994
4995    scoped_ptr<HttpTransaction> trans(
4996        new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4997
4998    MockWrite data_writes1[] = {
4999      MockWrite("GET /x/y/z2 HTTP/1.1\r\n"
5000                "Host: www.google.com\r\n"
5001                "Connection: keep-alive\r\n"
5002                // The authorization for MyRealm1 gets sent preemptively
5003                // (since the url is in the same protection space)
5004                "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5005    };
5006
5007    // Sever accepts the preemptive authorization
5008    MockRead data_reads1[] = {
5009      MockRead("HTTP/1.0 200 OK\r\n"),
5010      MockRead("Content-Length: 100\r\n\r\n"),
5011      MockRead(SYNCHRONOUS, OK),
5012    };
5013
5014    StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5015                                   data_writes1, arraysize(data_writes1));
5016    session_deps_.socket_factory->AddSocketDataProvider(&data1);
5017
5018    TestCompletionCallback callback1;
5019
5020    int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5021    EXPECT_EQ(ERR_IO_PENDING, rv);
5022
5023    rv = callback1.WaitForResult();
5024    EXPECT_EQ(OK, rv);
5025
5026    const HttpResponseInfo* response = trans->GetResponseInfo();
5027    ASSERT_TRUE(response != NULL);
5028
5029    EXPECT_TRUE(response->auth_challenge.get() == NULL);
5030    EXPECT_EQ(100, response->headers->GetContentLength());
5031  }
5032
5033  // ------------------------------------------------------------------------
5034
5035  // Transaction 4: request another URL in MyRealm (however the
5036  // url is not known to belong to the protection space, so no pre-auth).
5037  {
5038    HttpRequestInfo request;
5039    request.method = "GET";
5040    request.url = GURL("http://www.google.com/x/1");
5041    request.load_flags = 0;
5042
5043    scoped_ptr<HttpTransaction> trans(
5044        new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5045
5046    MockWrite data_writes1[] = {
5047      MockWrite("GET /x/1 HTTP/1.1\r\n"
5048                "Host: www.google.com\r\n"
5049                "Connection: keep-alive\r\n\r\n"),
5050    };
5051
5052    MockRead data_reads1[] = {
5053      MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5054      MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5055      MockRead("Content-Length: 10000\r\n\r\n"),
5056      MockRead(SYNCHRONOUS, ERR_FAILED),
5057    };
5058
5059    // Resend with authorization from MyRealm's cache.
5060    MockWrite data_writes2[] = {
5061      MockWrite("GET /x/1 HTTP/1.1\r\n"
5062                "Host: www.google.com\r\n"
5063                "Connection: keep-alive\r\n"
5064                "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5065    };
5066
5067    // Sever accepts the authorization.
5068    MockRead data_reads2[] = {
5069      MockRead("HTTP/1.0 200 OK\r\n"),
5070      MockRead("Content-Length: 100\r\n\r\n"),
5071      MockRead(SYNCHRONOUS, OK),
5072    };
5073
5074    StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5075                                   data_writes1, arraysize(data_writes1));
5076    StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5077                                   data_writes2, arraysize(data_writes2));
5078    session_deps_.socket_factory->AddSocketDataProvider(&data1);
5079    session_deps_.socket_factory->AddSocketDataProvider(&data2);
5080
5081    TestCompletionCallback callback1;
5082
5083    int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5084    EXPECT_EQ(ERR_IO_PENDING, rv);
5085
5086    rv = callback1.WaitForResult();
5087    EXPECT_EQ(OK, rv);
5088
5089    EXPECT_TRUE(trans->IsReadyToRestartForAuth());
5090    TestCompletionCallback callback2;
5091    rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
5092    EXPECT_EQ(ERR_IO_PENDING, rv);
5093    rv = callback2.WaitForResult();
5094    EXPECT_EQ(OK, rv);
5095    EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5096
5097    const HttpResponseInfo* response = trans->GetResponseInfo();
5098    ASSERT_TRUE(response != NULL);
5099    EXPECT_TRUE(response->auth_challenge.get() == NULL);
5100    EXPECT_EQ(100, response->headers->GetContentLength());
5101  }
5102
5103  // ------------------------------------------------------------------------
5104
5105  // Transaction 5: request a URL in MyRealm, but the server rejects the
5106  // cached identity. Should invalidate and re-prompt.
5107  {
5108    HttpRequestInfo request;
5109    request.method = "GET";
5110    request.url = GURL("http://www.google.com/p/q/t");
5111    request.load_flags = 0;
5112
5113    scoped_ptr<HttpTransaction> trans(
5114        new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5115
5116    MockWrite data_writes1[] = {
5117      MockWrite("GET /p/q/t HTTP/1.1\r\n"
5118                "Host: www.google.com\r\n"
5119                "Connection: keep-alive\r\n\r\n"),
5120    };
5121
5122    MockRead data_reads1[] = {
5123      MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5124      MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5125      MockRead("Content-Length: 10000\r\n\r\n"),
5126      MockRead(SYNCHRONOUS, ERR_FAILED),
5127    };
5128
5129    // Resend with authorization from cache for MyRealm.
5130    MockWrite data_writes2[] = {
5131      MockWrite("GET /p/q/t HTTP/1.1\r\n"
5132                "Host: www.google.com\r\n"
5133                "Connection: keep-alive\r\n"
5134                "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5135    };
5136
5137    // Sever rejects the authorization.
5138    MockRead data_reads2[] = {
5139      MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5140      MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5141      MockRead("Content-Length: 10000\r\n\r\n"),
5142      MockRead(SYNCHRONOUS, ERR_FAILED),
5143    };
5144
5145    // At this point we should prompt for new credentials for MyRealm.
5146    // Restart with username=foo3, password=foo4.
5147    MockWrite data_writes3[] = {
5148      MockWrite("GET /p/q/t HTTP/1.1\r\n"
5149                "Host: www.google.com\r\n"
5150                "Connection: keep-alive\r\n"
5151                "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
5152    };
5153
5154    // Sever accepts the authorization.
5155    MockRead data_reads3[] = {
5156      MockRead("HTTP/1.0 200 OK\r\n"),
5157      MockRead("Content-Length: 100\r\n\r\n"),
5158      MockRead(SYNCHRONOUS, OK),
5159    };
5160
5161    StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5162                                   data_writes1, arraysize(data_writes1));
5163    StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5164                                   data_writes2, arraysize(data_writes2));
5165    StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
5166                                   data_writes3, arraysize(data_writes3));
5167    session_deps_.socket_factory->AddSocketDataProvider(&data1);
5168    session_deps_.socket_factory->AddSocketDataProvider(&data2);
5169    session_deps_.socket_factory->AddSocketDataProvider(&data3);
5170
5171    TestCompletionCallback callback1;
5172
5173    int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5174    EXPECT_EQ(ERR_IO_PENDING, rv);
5175
5176    rv = callback1.WaitForResult();
5177    EXPECT_EQ(OK, rv);
5178
5179    EXPECT_TRUE(trans->IsReadyToRestartForAuth());
5180    TestCompletionCallback callback2;
5181    rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
5182    EXPECT_EQ(ERR_IO_PENDING, rv);
5183    rv = callback2.WaitForResult();
5184    EXPECT_EQ(OK, rv);
5185    EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5186
5187    const HttpResponseInfo* response = trans->GetResponseInfo();
5188    ASSERT_TRUE(response != NULL);
5189    EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
5190
5191    TestCompletionCallback callback3;
5192
5193    rv = trans->RestartWithAuth(
5194        AuthCredentials(kFoo3, kBar3), callback3.callback());
5195    EXPECT_EQ(ERR_IO_PENDING, rv);
5196
5197    rv = callback3.WaitForResult();
5198    EXPECT_EQ(OK, rv);
5199
5200    response = trans->GetResponseInfo();
5201    ASSERT_TRUE(response != NULL);
5202    EXPECT_TRUE(response->auth_challenge.get() == NULL);
5203    EXPECT_EQ(100, response->headers->GetContentLength());
5204  }
5205}
5206
5207// Tests that nonce count increments when multiple auth attempts
5208// are started with the same nonce.
5209TEST_P(HttpNetworkTransactionTest, DigestPreAuthNonceCount) {
5210  HttpAuthHandlerDigest::Factory* digest_factory =
5211      new HttpAuthHandlerDigest::Factory();
5212  HttpAuthHandlerDigest::FixedNonceGenerator* nonce_generator =
5213      new HttpAuthHandlerDigest::FixedNonceGenerator("0123456789abcdef");
5214  digest_factory->set_nonce_generator(nonce_generator);
5215  session_deps_.http_auth_handler_factory.reset(digest_factory);
5216  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5217
5218  // Transaction 1: authenticate (foo, bar) on MyRealm1
5219  {
5220    HttpRequestInfo request;
5221    request.method = "GET";
5222    request.url = GURL("http://www.google.com/x/y/z");
5223    request.load_flags = 0;
5224
5225    scoped_ptr<HttpTransaction> trans(
5226        new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5227
5228    MockWrite data_writes1[] = {
5229      MockWrite("GET /x/y/z HTTP/1.1\r\n"
5230                "Host: www.google.com\r\n"
5231                "Connection: keep-alive\r\n\r\n"),
5232    };
5233
5234    MockRead data_reads1[] = {
5235      MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5236      MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
5237               "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
5238      MockRead(SYNCHRONOUS, OK),
5239    };
5240
5241    // Resend with authorization (username=foo, password=bar)
5242    MockWrite data_writes2[] = {
5243      MockWrite("GET /x/y/z HTTP/1.1\r\n"
5244                "Host: www.google.com\r\n"
5245                "Connection: keep-alive\r\n"
5246                "Authorization: Digest username=\"foo\", realm=\"digestive\", "
5247                "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
5248                "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
5249                "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
5250    };
5251
5252    // Sever accepts the authorization.
5253    MockRead data_reads2[] = {
5254      MockRead("HTTP/1.0 200 OK\r\n"),
5255      MockRead(SYNCHRONOUS, OK),
5256    };
5257
5258    StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5259                                   data_writes1, arraysize(data_writes1));
5260    StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5261                                   data_writes2, arraysize(data_writes2));
5262    session_deps_.socket_factory->AddSocketDataProvider(&data1);
5263    session_deps_.socket_factory->AddSocketDataProvider(&data2);
5264
5265    TestCompletionCallback callback1;
5266
5267    int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5268    EXPECT_EQ(ERR_IO_PENDING, rv);
5269
5270    rv = callback1.WaitForResult();
5271    EXPECT_EQ(OK, rv);
5272
5273    const HttpResponseInfo* response = trans->GetResponseInfo();
5274    ASSERT_TRUE(response != NULL);
5275    EXPECT_TRUE(CheckDigestServerAuth(response->auth_challenge.get()));
5276
5277    TestCompletionCallback callback2;
5278
5279    rv = trans->RestartWithAuth(
5280        AuthCredentials(kFoo, kBar), callback2.callback());
5281    EXPECT_EQ(ERR_IO_PENDING, rv);
5282
5283    rv = callback2.WaitForResult();
5284    EXPECT_EQ(OK, rv);
5285
5286    response = trans->GetResponseInfo();
5287    ASSERT_TRUE(response != NULL);
5288    EXPECT_TRUE(response->auth_challenge.get() == NULL);
5289  }
5290
5291  // ------------------------------------------------------------------------
5292
5293  // Transaction 2: Request another resource in digestive's protection space.
5294  // This will preemptively add an Authorization header which should have an
5295  // "nc" value of 2 (as compared to 1 in the first use.
5296  {
5297    HttpRequestInfo request;
5298    request.method = "GET";
5299    // Note that Transaction 1 was at /x/y/z, so this is in the same
5300    // protection space as digest.
5301    request.url = GURL("http://www.google.com/x/y/a/b");
5302    request.load_flags = 0;
5303
5304    scoped_ptr<HttpTransaction> trans(
5305        new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5306
5307    MockWrite data_writes1[] = {
5308      MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
5309                "Host: www.google.com\r\n"
5310                "Connection: keep-alive\r\n"
5311                "Authorization: Digest username=\"foo\", realm=\"digestive\", "
5312                "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
5313                "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
5314                "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
5315    };
5316
5317    // Sever accepts the authorization.
5318    MockRead data_reads1[] = {
5319      MockRead("HTTP/1.0 200 OK\r\n"),
5320      MockRead("Content-Length: 100\r\n\r\n"),
5321      MockRead(SYNCHRONOUS, OK),
5322    };
5323
5324    StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5325                                   data_writes1, arraysize(data_writes1));
5326    session_deps_.socket_factory->AddSocketDataProvider(&data1);
5327
5328    TestCompletionCallback callback1;
5329
5330    int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5331    EXPECT_EQ(ERR_IO_PENDING, rv);
5332
5333    rv = callback1.WaitForResult();
5334    EXPECT_EQ(OK, rv);
5335
5336    const HttpResponseInfo* response = trans->GetResponseInfo();
5337    ASSERT_TRUE(response != NULL);
5338    EXPECT_TRUE(response->auth_challenge.get() == NULL);
5339  }
5340}
5341
5342// Test the ResetStateForRestart() private method.
5343TEST_P(HttpNetworkTransactionTest, ResetStateForRestart) {
5344  // Create a transaction (the dependencies aren't important).
5345  scoped_ptr<HttpNetworkTransaction> trans(
5346      new HttpNetworkTransaction(DEFAULT_PRIORITY,
5347                                 CreateSession(&session_deps_)));
5348
5349  // Setup some state (which we expect ResetStateForRestart() will clear).
5350  trans->read_buf_ = new IOBuffer(15);
5351  trans->read_buf_len_ = 15;
5352  trans->request_headers_.SetHeader("Authorization", "NTLM");
5353
5354  // Setup state in response_
5355  HttpResponseInfo* response = &trans->response_;
5356  response->auth_challenge = new AuthChallengeInfo();
5357  response->ssl_info.cert_status = static_cast<CertStatus>(-1);  // Nonsensical.
5358  response->response_time = base::Time::Now();
5359  response->was_cached = true;  // (Wouldn't ever actually be true...)
5360
5361  { // Setup state for response_.vary_data
5362    HttpRequestInfo request;
5363    std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
5364    std::replace(temp.begin(), temp.end(), '\n', '\0');
5365    scoped_refptr<HttpResponseHeaders> headers(new HttpResponseHeaders(temp));
5366    request.extra_headers.SetHeader("Foo", "1");
5367    request.extra_headers.SetHeader("bar", "23");
5368    EXPECT_TRUE(response->vary_data.Init(request, *headers.get()));
5369  }
5370
5371  // Cause the above state to be reset.
5372  trans->ResetStateForRestart();
5373
5374  // Verify that the state that needed to be reset, has been reset.
5375  EXPECT_TRUE(trans->read_buf_.get() == NULL);
5376  EXPECT_EQ(0, trans->read_buf_len_);
5377  EXPECT_TRUE(trans->request_headers_.IsEmpty());
5378  EXPECT_TRUE(response->auth_challenge.get() == NULL);
5379  EXPECT_TRUE(response->headers.get() == NULL);
5380  EXPECT_FALSE(response->was_cached);
5381  EXPECT_EQ(0U, response->ssl_info.cert_status);
5382  EXPECT_FALSE(response->vary_data.is_valid());
5383}
5384
5385// Test HTTPS connections to a site with a bad certificate
5386TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificate) {
5387  HttpRequestInfo request;
5388  request.method = "GET";
5389  request.url = GURL("https://www.google.com/");
5390  request.load_flags = 0;
5391
5392  scoped_ptr<HttpTransaction> trans(
5393      new HttpNetworkTransaction(DEFAULT_PRIORITY,
5394                                 CreateSession(&session_deps_)));
5395
5396  MockWrite data_writes[] = {
5397    MockWrite("GET / HTTP/1.1\r\n"
5398              "Host: www.google.com\r\n"
5399              "Connection: keep-alive\r\n\r\n"),
5400  };
5401
5402  MockRead data_reads[] = {
5403    MockRead("HTTP/1.0 200 OK\r\n"),
5404    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5405    MockRead("Content-Length: 100\r\n\r\n"),
5406    MockRead(SYNCHRONOUS, OK),
5407  };
5408
5409  StaticSocketDataProvider ssl_bad_certificate;
5410  StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5411                                data_writes, arraysize(data_writes));
5412  SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
5413  SSLSocketDataProvider ssl(ASYNC, OK);
5414
5415  session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
5416  session_deps_.socket_factory->AddSocketDataProvider(&data);
5417  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
5418  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
5419
5420  TestCompletionCallback callback;
5421
5422  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5423  EXPECT_EQ(ERR_IO_PENDING, rv);
5424
5425  rv = callback.WaitForResult();
5426  EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
5427
5428  rv = trans->RestartIgnoringLastError(callback.callback());
5429  EXPECT_EQ(ERR_IO_PENDING, rv);
5430
5431  rv = callback.WaitForResult();
5432  EXPECT_EQ(OK, rv);
5433
5434  const HttpResponseInfo* response = trans->GetResponseInfo();
5435
5436  ASSERT_TRUE(response != NULL);
5437  EXPECT_EQ(100, response->headers->GetContentLength());
5438}
5439
5440// Test HTTPS connections to a site with a bad certificate, going through a
5441// proxy
5442TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
5443  session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
5444
5445  HttpRequestInfo request;
5446  request.method = "GET";
5447  request.url = GURL("https://www.google.com/");
5448  request.load_flags = 0;
5449
5450  MockWrite proxy_writes[] = {
5451    MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
5452              "Host: www.google.com\r\n"
5453              "Proxy-Connection: keep-alive\r\n\r\n"),
5454  };
5455
5456  MockRead proxy_reads[] = {
5457    MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
5458    MockRead(SYNCHRONOUS, OK)
5459  };
5460
5461  MockWrite data_writes[] = {
5462    MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
5463              "Host: www.google.com\r\n"
5464              "Proxy-Connection: keep-alive\r\n\r\n"),
5465    MockWrite("GET / HTTP/1.1\r\n"
5466              "Host: www.google.com\r\n"
5467              "Connection: keep-alive\r\n\r\n"),
5468  };
5469
5470  MockRead data_reads[] = {
5471    MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
5472    MockRead("HTTP/1.0 200 OK\r\n"),
5473    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5474    MockRead("Content-Length: 100\r\n\r\n"),
5475    MockRead(SYNCHRONOUS, OK),
5476  };
5477
5478  StaticSocketDataProvider ssl_bad_certificate(
5479      proxy_reads, arraysize(proxy_reads),
5480      proxy_writes, arraysize(proxy_writes));
5481  StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5482                                data_writes, arraysize(data_writes));
5483  SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
5484  SSLSocketDataProvider ssl(ASYNC, OK);
5485
5486  session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
5487  session_deps_.socket_factory->AddSocketDataProvider(&data);
5488  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
5489  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
5490
5491  TestCompletionCallback callback;
5492
5493  for (int i = 0; i < 2; i++) {
5494    session_deps_.socket_factory->ResetNextMockIndexes();
5495
5496    scoped_ptr<HttpTransaction> trans(
5497        new HttpNetworkTransaction(DEFAULT_PRIORITY,
5498                                   CreateSession(&session_deps_)));
5499
5500    int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5501    EXPECT_EQ(ERR_IO_PENDING, rv);
5502
5503    rv = callback.WaitForResult();
5504    EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
5505
5506    rv = trans->RestartIgnoringLastError(callback.callback());
5507    EXPECT_EQ(ERR_IO_PENDING, rv);
5508
5509    rv = callback.WaitForResult();
5510    EXPECT_EQ(OK, rv);
5511
5512    const HttpResponseInfo* response = trans->GetResponseInfo();
5513
5514    ASSERT_TRUE(response != NULL);
5515    EXPECT_EQ(100, response->headers->GetContentLength());
5516  }
5517}
5518
5519
5520// Test HTTPS connections to a site, going through an HTTPS proxy
5521TEST_P(HttpNetworkTransactionTest, HTTPSViaHttpsProxy) {
5522  session_deps_.proxy_service.reset(
5523      ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
5524  CapturingNetLog net_log;
5525  session_deps_.net_log = &net_log;
5526
5527  HttpRequestInfo request;
5528  request.method = "GET";
5529  request.url = GURL("https://www.google.com/");
5530  request.load_flags = 0;
5531
5532  MockWrite data_writes[] = {
5533    MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
5534              "Host: www.google.com\r\n"
5535              "Proxy-Connection: keep-alive\r\n\r\n"),
5536    MockWrite("GET / HTTP/1.1\r\n"
5537              "Host: www.google.com\r\n"
5538              "Connection: keep-alive\r\n\r\n"),
5539  };
5540
5541  MockRead data_reads[] = {
5542    MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
5543    MockRead("HTTP/1.1 200 OK\r\n"),
5544    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5545    MockRead("Content-Length: 100\r\n\r\n"),
5546    MockRead(SYNCHRONOUS, OK),
5547  };
5548
5549  StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5550                                data_writes, arraysize(data_writes));
5551  SSLSocketDataProvider proxy_ssl(ASYNC, OK);  // SSL to the proxy
5552  SSLSocketDataProvider tunnel_ssl(ASYNC, OK);  // SSL through the tunnel
5553
5554  session_deps_.socket_factory->AddSocketDataProvider(&data);
5555  session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
5556  session_deps_.socket_factory->AddSSLSocketDataProvider(&tunnel_ssl);
5557
5558  TestCompletionCallback callback;
5559
5560  scoped_ptr<HttpTransaction> trans(
5561      new HttpNetworkTransaction(DEFAULT_PRIORITY,
5562                                 CreateSession(&session_deps_)));
5563
5564  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5565  EXPECT_EQ(ERR_IO_PENDING, rv);
5566
5567  rv = callback.WaitForResult();
5568  EXPECT_EQ(OK, rv);
5569  const HttpResponseInfo* response = trans->GetResponseInfo();
5570
5571  ASSERT_TRUE(response != NULL);
5572
5573  EXPECT_TRUE(response->headers->IsKeepAlive());
5574  EXPECT_EQ(200, response->headers->response_code());
5575  EXPECT_EQ(100, response->headers->GetContentLength());
5576  EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
5577
5578  LoadTimingInfo load_timing_info;
5579  EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
5580  TestLoadTimingNotReusedWithPac(load_timing_info,
5581                                 CONNECT_TIMING_HAS_SSL_TIMES);
5582}
5583
5584// Test an HTTPS Proxy's ability to redirect a CONNECT request
5585TEST_P(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaHttpsProxy) {
5586  session_deps_.proxy_service.reset(
5587      ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
5588  CapturingNetLog net_log;
5589  session_deps_.net_log = &net_log;
5590
5591  HttpRequestInfo request;
5592  request.method = "GET";
5593  request.url = GURL("https://www.google.com/");
5594  request.load_flags = 0;
5595
5596  MockWrite data_writes[] = {
5597    MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
5598              "Host: www.google.com\r\n"
5599              "Proxy-Connection: keep-alive\r\n\r\n"),
5600  };
5601
5602  MockRead data_reads[] = {
5603    MockRead("HTTP/1.1 302 Redirect\r\n"),
5604    MockRead("Location: http://login.example.com/\r\n"),
5605    MockRead("Content-Length: 0\r\n\r\n"),
5606    MockRead(SYNCHRONOUS, OK),
5607  };
5608
5609  StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5610                                data_writes, arraysize(data_writes));
5611  SSLSocketDataProvider proxy_ssl(ASYNC, OK);  // SSL to the proxy
5612
5613  session_deps_.socket_factory->AddSocketDataProvider(&data);
5614  session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
5615
5616  TestCompletionCallback callback;
5617
5618  scoped_ptr<HttpTransaction> trans(
5619      new HttpNetworkTransaction(DEFAULT_PRIORITY,
5620                                 CreateSession(&session_deps_)));
5621
5622  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5623  EXPECT_EQ(ERR_IO_PENDING, rv);
5624
5625  rv = callback.WaitForResult();
5626  EXPECT_EQ(OK, rv);
5627  const HttpResponseInfo* response = trans->GetResponseInfo();
5628
5629  ASSERT_TRUE(response != NULL);
5630
5631  EXPECT_EQ(302, response->headers->response_code());
5632  std::string url;
5633  EXPECT_TRUE(response->headers->IsRedirect(&url));
5634  EXPECT_EQ("http://login.example.com/", url);
5635
5636  // In the case of redirects from proxies, HttpNetworkTransaction returns
5637  // timing for the proxy connection instead of the connection to the host,
5638  // and no send / receive times.
5639  // See HttpNetworkTransaction::OnHttpsProxyTunnelResponse.
5640  LoadTimingInfo load_timing_info;
5641  EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
5642
5643  EXPECT_FALSE(load_timing_info.socket_reused);
5644  EXPECT_NE(net::NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
5645
5646  EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null());
5647  EXPECT_LE(load_timing_info.proxy_resolve_start,
5648            load_timing_info.proxy_resolve_end);
5649  EXPECT_LE(load_timing_info.proxy_resolve_end,
5650            load_timing_info.connect_timing.connect_start);
5651  ExpectConnectTimingHasTimes(
5652      load_timing_info.connect_timing,
5653      CONNECT_TIMING_HAS_DNS_TIMES | CONNECT_TIMING_HAS_SSL_TIMES);
5654
5655  EXPECT_TRUE(load_timing_info.send_start.is_null());
5656  EXPECT_TRUE(load_timing_info.send_end.is_null());
5657  EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
5658}
5659
5660// Test an HTTPS (SPDY) Proxy's ability to redirect a CONNECT request
5661TEST_P(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaSpdyProxy) {
5662  session_deps_.proxy_service.reset(
5663      ProxyService::CreateFixed("https://proxy:70"));
5664
5665  HttpRequestInfo request;
5666  request.method = "GET";
5667  request.url = GURL("https://www.google.com/");
5668  request.load_flags = 0;
5669
5670  scoped_ptr<SpdyFrame> conn(spdy_util_.ConstructSpdyConnect(NULL, 0, 1));
5671  scoped_ptr<SpdyFrame> goaway(
5672      spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
5673  MockWrite data_writes[] = {
5674    CreateMockWrite(*conn.get(), 0, SYNCHRONOUS),
5675    CreateMockWrite(*goaway.get(), 3, SYNCHRONOUS),
5676  };
5677
5678  static const char* const kExtraHeaders[] = {
5679    "location",
5680    "http://login.example.com/",
5681  };
5682  scoped_ptr<SpdyFrame> resp(
5683      spdy_util_.ConstructSpdySynReplyError("302 Redirect", kExtraHeaders,
5684                                 arraysize(kExtraHeaders)/2, 1));
5685  MockRead data_reads[] = {
5686    CreateMockRead(*resp.get(), 1, SYNCHRONOUS),
5687    MockRead(ASYNC, 0, 2),  // EOF
5688  };
5689
5690  DelayedSocketData data(
5691      1,  // wait for one write to finish before reading.
5692      data_reads, arraysize(data_reads),
5693      data_writes, arraysize(data_writes));
5694  SSLSocketDataProvider proxy_ssl(ASYNC, OK);  // SSL to the proxy
5695  proxy_ssl.SetNextProto(GetParam());
5696
5697  session_deps_.socket_factory->AddSocketDataProvider(&data);
5698  session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
5699
5700  TestCompletionCallback callback;
5701
5702  scoped_ptr<HttpTransaction> trans(
5703      new HttpNetworkTransaction(DEFAULT_PRIORITY,
5704                                 CreateSession(&session_deps_)));
5705
5706  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5707  EXPECT_EQ(ERR_IO_PENDING, rv);
5708
5709  rv = callback.WaitForResult();
5710  EXPECT_EQ(OK, rv);
5711  const HttpResponseInfo* response = trans->GetResponseInfo();
5712
5713  ASSERT_TRUE(response != NULL);
5714
5715  EXPECT_EQ(302, response->headers->response_code());
5716  std::string url;
5717  EXPECT_TRUE(response->headers->IsRedirect(&url));
5718  EXPECT_EQ("http://login.example.com/", url);
5719}
5720
5721// Test that an HTTPS proxy's response to a CONNECT request is filtered.
5722TEST_P(HttpNetworkTransactionTest,
5723       ErrorResponseToHttpsConnectViaHttpsProxy) {
5724  session_deps_.proxy_service.reset(
5725      ProxyService::CreateFixed("https://proxy:70"));
5726
5727  HttpRequestInfo request;
5728  request.method = "GET";
5729  request.url = GURL("https://www.google.com/");
5730  request.load_flags = 0;
5731
5732  MockWrite data_writes[] = {
5733    MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
5734              "Host: www.google.com\r\n"
5735              "Proxy-Connection: keep-alive\r\n\r\n"),
5736  };
5737
5738  MockRead data_reads[] = {
5739    MockRead("HTTP/1.1 404 Not Found\r\n"),
5740    MockRead("Content-Length: 23\r\n\r\n"),
5741    MockRead("The host does not exist"),
5742    MockRead(SYNCHRONOUS, OK),
5743  };
5744
5745  StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5746                                data_writes, arraysize(data_writes));
5747  SSLSocketDataProvider proxy_ssl(ASYNC, OK);  // SSL to the proxy
5748
5749  session_deps_.socket_factory->AddSocketDataProvider(&data);
5750  session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
5751
5752  TestCompletionCallback callback;
5753
5754  scoped_ptr<HttpTransaction> trans(
5755      new HttpNetworkTransaction(DEFAULT_PRIORITY,
5756                                 CreateSession(&session_deps_)));
5757
5758  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5759  EXPECT_EQ(ERR_IO_PENDING, rv);
5760
5761  rv = callback.WaitForResult();
5762  EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
5763
5764  // TODO(ttuttle): Anything else to check here?
5765}
5766
5767// Test that a SPDY proxy's response to a CONNECT request is filtered.
5768TEST_P(HttpNetworkTransactionTest,
5769       ErrorResponseToHttpsConnectViaSpdyProxy) {
5770  session_deps_.proxy_service.reset(
5771     ProxyService::CreateFixed("https://proxy:70"));
5772
5773  HttpRequestInfo request;
5774  request.method = "GET";
5775  request.url = GURL("https://www.google.com/");
5776  request.load_flags = 0;
5777
5778  scoped_ptr<SpdyFrame> conn(spdy_util_.ConstructSpdyConnect(NULL, 0, 1));
5779  scoped_ptr<SpdyFrame> rst(
5780      spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
5781  MockWrite data_writes[] = {
5782    CreateMockWrite(*conn.get(), 0, SYNCHRONOUS),
5783    CreateMockWrite(*rst.get(), 3, SYNCHRONOUS),
5784  };
5785
5786  static const char* const kExtraHeaders[] = {
5787    "location",
5788    "http://login.example.com/",
5789  };
5790  scoped_ptr<SpdyFrame> resp(
5791      spdy_util_.ConstructSpdySynReplyError("404 Not Found", kExtraHeaders,
5792                                 arraysize(kExtraHeaders)/2, 1));
5793  scoped_ptr<SpdyFrame> body(
5794      spdy_util_.ConstructSpdyBodyFrame(
5795          1, "The host does not exist", 23, true));
5796  MockRead data_reads[] = {
5797    CreateMockRead(*resp.get(), 1, SYNCHRONOUS),
5798    CreateMockRead(*body.get(), 2, SYNCHRONOUS),
5799    MockRead(ASYNC, 0, 4),  // EOF
5800  };
5801
5802  DelayedSocketData data(
5803      1,  // wait for one write to finish before reading.
5804      data_reads, arraysize(data_reads),
5805      data_writes, arraysize(data_writes));
5806  SSLSocketDataProvider proxy_ssl(ASYNC, OK);  // SSL to the proxy
5807  proxy_ssl.SetNextProto(GetParam());
5808
5809  session_deps_.socket_factory->AddSocketDataProvider(&data);
5810  session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
5811
5812  TestCompletionCallback callback;
5813
5814  scoped_ptr<HttpTransaction> trans(
5815      new HttpNetworkTransaction(DEFAULT_PRIORITY,
5816                                 CreateSession(&session_deps_)));
5817
5818  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5819  EXPECT_EQ(ERR_IO_PENDING, rv);
5820
5821  rv = callback.WaitForResult();
5822  EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
5823
5824  // TODO(ttuttle): Anything else to check here?
5825}
5826
5827// Test the request-challenge-retry sequence for basic auth, through
5828// a SPDY proxy over a single SPDY session.
5829TEST_P(HttpNetworkTransactionTest, BasicAuthSpdyProxy) {
5830  HttpRequestInfo request;
5831  request.method = "GET";
5832  request.url = GURL("https://www.google.com/");
5833  // when the no authentication data flag is set.
5834  request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
5835
5836  // Configure against https proxy server "myproxy:70".
5837  session_deps_.proxy_service.reset(
5838      ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70"));
5839  CapturingBoundNetLog log;
5840  session_deps_.net_log = log.bound().net_log();
5841  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5842
5843  // Since we have proxy, should try to establish tunnel.
5844  scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyConnect(NULL, 0, 1));
5845  scoped_ptr<SpdyFrame> rst(
5846      spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
5847
5848  // After calling trans->RestartWithAuth(), this is the request we should
5849  // be issuing -- the final header line contains the credentials.
5850  const char* const kAuthCredentials[] = {
5851      "proxy-authorization", "Basic Zm9vOmJhcg==",
5852  };
5853  scoped_ptr<SpdyFrame> connect2(spdy_util_.ConstructSpdyConnect(
5854      kAuthCredentials, arraysize(kAuthCredentials) / 2, 3));
5855  // fetch https://www.google.com/ via HTTP
5856  const char get[] = "GET / HTTP/1.1\r\n"
5857    "Host: www.google.com\r\n"
5858    "Connection: keep-alive\r\n\r\n";
5859  scoped_ptr<SpdyFrame> wrapped_get(
5860      spdy_util_.ConstructSpdyBodyFrame(3, get, strlen(get), false));
5861
5862  MockWrite spdy_writes[] = {
5863    CreateMockWrite(*req, 1, ASYNC),
5864    CreateMockWrite(*rst, 4, ASYNC),
5865    CreateMockWrite(*connect2, 5),
5866    CreateMockWrite(*wrapped_get, 8),
5867  };
5868
5869  // The proxy responds to the connect with a 407, using a persistent
5870  // connection.
5871  const char* const kAuthChallenge[] = {
5872    spdy_util_.GetStatusKey(), "407 Proxy Authentication Required",
5873    spdy_util_.GetVersionKey(), "HTTP/1.1",
5874    "proxy-authenticate", "Basic realm=\"MyRealm1\"",
5875  };
5876
5877  scoped_ptr<SpdyFrame> conn_auth_resp(
5878      spdy_util_.ConstructSpdyControlFrame(NULL,
5879                                           0,
5880                                           false,
5881                                           1,
5882                                           LOWEST,
5883                                           SYN_REPLY,
5884                                           CONTROL_FLAG_NONE,
5885                                           kAuthChallenge,
5886                                           arraysize(kAuthChallenge),
5887                                           0));
5888
5889  scoped_ptr<SpdyFrame> conn_resp(
5890      spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
5891  const char resp[] = "HTTP/1.1 200 OK\r\n"
5892      "Content-Length: 5\r\n\r\n";
5893
5894  scoped_ptr<SpdyFrame> wrapped_get_resp(
5895      spdy_util_.ConstructSpdyBodyFrame(3, resp, strlen(resp), false));
5896  scoped_ptr<SpdyFrame> wrapped_body(
5897      spdy_util_.ConstructSpdyBodyFrame(3, "hello", 5, false));
5898  MockRead spdy_reads[] = {
5899    CreateMockRead(*conn_auth_resp, 2, ASYNC),
5900    CreateMockRead(*conn_resp, 6, ASYNC),
5901    CreateMockRead(*wrapped_get_resp, 9, ASYNC),
5902    CreateMockRead(*wrapped_body, 10, ASYNC),
5903    MockRead(ASYNC, OK, 11),  // EOF.  May or may not be read.
5904  };
5905
5906  OrderedSocketData spdy_data(
5907      spdy_reads, arraysize(spdy_reads),
5908      spdy_writes, arraysize(spdy_writes));
5909  session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
5910  // Negotiate SPDY to the proxy
5911  SSLSocketDataProvider proxy(ASYNC, OK);
5912  proxy.SetNextProto(GetParam());
5913  session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
5914  // Vanilla SSL to the server
5915  SSLSocketDataProvider server(ASYNC, OK);
5916  session_deps_.socket_factory->AddSSLSocketDataProvider(&server);
5917
5918  TestCompletionCallback callback1;
5919
5920  scoped_ptr<HttpTransaction> trans(
5921      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5922
5923  int rv = trans->Start(&request, callback1.callback(), log.bound());
5924  EXPECT_EQ(ERR_IO_PENDING, rv);
5925
5926  rv = callback1.WaitForResult();
5927  EXPECT_EQ(OK, rv);
5928  net::CapturingNetLog::CapturedEntryList entries;
5929  log.GetEntries(&entries);
5930  size_t pos = ExpectLogContainsSomewhere(
5931      entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
5932      NetLog::PHASE_NONE);
5933  ExpectLogContainsSomewhere(
5934      entries, pos,
5935      NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
5936      NetLog::PHASE_NONE);
5937
5938  const HttpResponseInfo* response = trans->GetResponseInfo();
5939  ASSERT_TRUE(response != NULL);
5940  ASSERT_FALSE(response->headers.get() == NULL);
5941  EXPECT_EQ(407, response->headers->response_code());
5942  EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
5943  EXPECT_TRUE(response->auth_challenge.get() != NULL);
5944  EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
5945
5946  TestCompletionCallback callback2;
5947
5948  rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar),
5949                              callback2.callback());
5950  EXPECT_EQ(ERR_IO_PENDING, rv);
5951
5952  rv = callback2.WaitForResult();
5953  EXPECT_EQ(OK, rv);
5954
5955  response = trans->GetResponseInfo();
5956  ASSERT_TRUE(response != NULL);
5957
5958  EXPECT_TRUE(response->headers->IsKeepAlive());
5959  EXPECT_EQ(200, response->headers->response_code());
5960  EXPECT_EQ(5, response->headers->GetContentLength());
5961  EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
5962
5963  // The password prompt info should not be set.
5964  EXPECT_TRUE(response->auth_challenge.get() == NULL);
5965
5966  LoadTimingInfo load_timing_info;
5967  EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
5968  TestLoadTimingNotReusedWithPac(load_timing_info,
5969                                 CONNECT_TIMING_HAS_SSL_TIMES);
5970
5971  trans.reset();
5972  session->CloseAllConnections();
5973}
5974
5975// Test that an explicitly trusted SPDY proxy can push a resource from an
5976// origin that is different from that of its associated resource.
5977TEST_P(HttpNetworkTransactionTest, CrossOriginProxyPush) {
5978  HttpRequestInfo request;
5979  HttpRequestInfo push_request;
5980
5981  request.method = "GET";
5982  request.url = GURL("http://www.google.com/");
5983  push_request.method = "GET";
5984  push_request.url = GURL("http://www.another-origin.com/foo.dat");
5985
5986  // Configure against https proxy server "myproxy:70".
5987  session_deps_.proxy_service.reset(
5988      ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70"));
5989  CapturingBoundNetLog log;
5990  session_deps_.net_log = log.bound().net_log();
5991
5992  // Enable cross-origin push.
5993  session_deps_.trusted_spdy_proxy = "myproxy:70";
5994
5995  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5996
5997  scoped_ptr<SpdyFrame> stream1_syn(
5998      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
5999
6000  MockWrite spdy_writes[] = {
6001    CreateMockWrite(*stream1_syn, 1, ASYNC),
6002  };
6003
6004  scoped_ptr<SpdyFrame>
6005      stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
6006
6007  scoped_ptr<SpdyFrame>
6008      stream1_body(spdy_util_.ConstructSpdyBodyFrame(1, true));
6009
6010  scoped_ptr<SpdyFrame>
6011      stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
6012                                    0,
6013                                    2,
6014                                    1,
6015                                    "http://www.another-origin.com/foo.dat"));
6016  const char kPushedData[] = "pushed";
6017  scoped_ptr<SpdyFrame> stream2_body(
6018      spdy_util_.ConstructSpdyBodyFrame(
6019          2, kPushedData, strlen(kPushedData), true));
6020
6021  MockRead spdy_reads[] = {
6022    CreateMockRead(*stream1_reply, 2, ASYNC),
6023    CreateMockRead(*stream2_syn, 3, ASYNC),
6024    CreateMockRead(*stream1_body, 4, ASYNC),
6025    CreateMockRead(*stream2_body, 5, ASYNC),
6026    MockRead(ASYNC, ERR_IO_PENDING, 6),  // Force a pause
6027  };
6028
6029  OrderedSocketData spdy_data(
6030      spdy_reads, arraysize(spdy_reads),
6031      spdy_writes, arraysize(spdy_writes));
6032  session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
6033  // Negotiate SPDY to the proxy
6034  SSLSocketDataProvider proxy(ASYNC, OK);
6035  proxy.SetNextProto(GetParam());
6036  session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
6037
6038  scoped_ptr<HttpTransaction> trans(
6039      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6040  TestCompletionCallback callback;
6041  int rv = trans->Start(&request, callback.callback(), log.bound());
6042  EXPECT_EQ(ERR_IO_PENDING, rv);
6043
6044  rv = callback.WaitForResult();
6045  EXPECT_EQ(OK, rv);
6046  const HttpResponseInfo* response = trans->GetResponseInfo();
6047
6048  scoped_ptr<HttpTransaction> push_trans(
6049      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6050  rv = push_trans->Start(&push_request, callback.callback(), log.bound());
6051  EXPECT_EQ(ERR_IO_PENDING, rv);
6052
6053  rv = callback.WaitForResult();
6054  EXPECT_EQ(OK, rv);
6055  const HttpResponseInfo* push_response = push_trans->GetResponseInfo();
6056
6057  ASSERT_TRUE(response != NULL);
6058  EXPECT_TRUE(response->headers->IsKeepAlive());
6059
6060  EXPECT_EQ(200, response->headers->response_code());
6061  EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
6062
6063  std::string response_data;
6064  rv = ReadTransaction(trans.get(), &response_data);
6065  EXPECT_EQ(OK, rv);
6066  EXPECT_EQ("hello!", response_data);
6067
6068  LoadTimingInfo load_timing_info;
6069  EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
6070  TestLoadTimingNotReusedWithPac(load_timing_info,
6071                                 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
6072
6073  // Verify the pushed stream.
6074  EXPECT_TRUE(push_response->headers.get() != NULL);
6075  EXPECT_EQ(200, push_response->headers->response_code());
6076
6077  rv = ReadTransaction(push_trans.get(), &response_data);
6078  EXPECT_EQ(OK, rv);
6079  EXPECT_EQ("pushed", response_data);
6080
6081  LoadTimingInfo push_load_timing_info;
6082  EXPECT_TRUE(push_trans->GetLoadTimingInfo(&push_load_timing_info));
6083  TestLoadTimingReusedWithPac(push_load_timing_info);
6084  // The transactions should share a socket ID, despite being for different
6085  // origins.
6086  EXPECT_EQ(load_timing_info.socket_log_id,
6087            push_load_timing_info.socket_log_id);
6088
6089  trans.reset();
6090  push_trans.reset();
6091  session->CloseAllConnections();
6092}
6093
6094// Test that an explicitly trusted SPDY proxy cannot push HTTPS content.
6095TEST_P(HttpNetworkTransactionTest, CrossOriginProxyPushCorrectness) {
6096  HttpRequestInfo request;
6097
6098  request.method = "GET";
6099  request.url = GURL("http://www.google.com/");
6100
6101  // Configure against https proxy server "myproxy:70".
6102  session_deps_.proxy_service.reset(
6103      ProxyService::CreateFixed("https://myproxy:70"));
6104  CapturingBoundNetLog log;
6105  session_deps_.net_log = log.bound().net_log();
6106
6107  // Enable cross-origin push.
6108  session_deps_.trusted_spdy_proxy = "myproxy:70";
6109
6110  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6111
6112  scoped_ptr<SpdyFrame> stream1_syn(
6113      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
6114
6115  scoped_ptr<SpdyFrame> push_rst(
6116      spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
6117
6118  MockWrite spdy_writes[] = {
6119    CreateMockWrite(*stream1_syn, 1, ASYNC),
6120    CreateMockWrite(*push_rst, 4),
6121  };
6122
6123  scoped_ptr<SpdyFrame>
6124      stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
6125
6126  scoped_ptr<SpdyFrame>
6127      stream1_body(spdy_util_.ConstructSpdyBodyFrame(1, true));
6128
6129  scoped_ptr<SpdyFrame>
6130      stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
6131                                    0,
6132                                    2,
6133                                    1,
6134                                    "https://www.another-origin.com/foo.dat"));
6135
6136  MockRead spdy_reads[] = {
6137    CreateMockRead(*stream1_reply, 2, ASYNC),
6138    CreateMockRead(*stream2_syn, 3, ASYNC),
6139    CreateMockRead(*stream1_body, 5, ASYNC),
6140    MockRead(ASYNC, ERR_IO_PENDING, 6),  // Force a pause
6141  };
6142
6143  OrderedSocketData spdy_data(
6144      spdy_reads, arraysize(spdy_reads),
6145      spdy_writes, arraysize(spdy_writes));
6146  session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
6147  // Negotiate SPDY to the proxy
6148  SSLSocketDataProvider proxy(ASYNC, OK);
6149  proxy.SetNextProto(GetParam());
6150  session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
6151
6152  scoped_ptr<HttpTransaction> trans(
6153      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6154  TestCompletionCallback callback;
6155  int rv = trans->Start(&request, callback.callback(), log.bound());
6156  EXPECT_EQ(ERR_IO_PENDING, rv);
6157
6158  rv = callback.WaitForResult();
6159  EXPECT_EQ(OK, rv);
6160  const HttpResponseInfo* response = trans->GetResponseInfo();
6161
6162  ASSERT_TRUE(response != NULL);
6163  EXPECT_TRUE(response->headers->IsKeepAlive());
6164
6165  EXPECT_EQ(200, response->headers->response_code());
6166  EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
6167
6168  std::string response_data;
6169  rv = ReadTransaction(trans.get(), &response_data);
6170  EXPECT_EQ(OK, rv);
6171  EXPECT_EQ("hello!", response_data);
6172
6173  trans.reset();
6174  session->CloseAllConnections();
6175}
6176
6177// Test HTTPS connections to a site with a bad certificate, going through an
6178// HTTPS proxy
6179TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificateViaHttpsProxy) {
6180  session_deps_.proxy_service.reset(ProxyService::CreateFixed(
6181      "https://proxy:70"));
6182
6183  HttpRequestInfo request;
6184  request.method = "GET";
6185  request.url = GURL("https://www.google.com/");
6186  request.load_flags = 0;
6187
6188  // Attempt to fetch the URL from a server with a bad cert
6189  MockWrite bad_cert_writes[] = {
6190    MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6191              "Host: www.google.com\r\n"
6192              "Proxy-Connection: keep-alive\r\n\r\n"),
6193  };
6194
6195  MockRead bad_cert_reads[] = {
6196    MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6197    MockRead(SYNCHRONOUS, OK)
6198  };
6199
6200  // Attempt to fetch the URL with a good cert
6201  MockWrite good_data_writes[] = {
6202    MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6203              "Host: www.google.com\r\n"
6204              "Proxy-Connection: keep-alive\r\n\r\n"),
6205    MockWrite("GET / HTTP/1.1\r\n"
6206              "Host: www.google.com\r\n"
6207              "Connection: keep-alive\r\n\r\n"),
6208  };
6209
6210  MockRead good_cert_reads[] = {
6211    MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6212    MockRead("HTTP/1.0 200 OK\r\n"),
6213    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6214    MockRead("Content-Length: 100\r\n\r\n"),
6215    MockRead(SYNCHRONOUS, OK),
6216  };
6217
6218  StaticSocketDataProvider ssl_bad_certificate(
6219      bad_cert_reads, arraysize(bad_cert_reads),
6220      bad_cert_writes, arraysize(bad_cert_writes));
6221  StaticSocketDataProvider data(good_cert_reads, arraysize(good_cert_reads),
6222                                good_data_writes, arraysize(good_data_writes));
6223  SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
6224  SSLSocketDataProvider ssl(ASYNC, OK);
6225
6226  // SSL to the proxy, then CONNECT request, then SSL with bad certificate
6227  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6228  session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
6229  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
6230
6231  // SSL to the proxy, then CONNECT request, then valid SSL certificate
6232  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6233  session_deps_.socket_factory->AddSocketDataProvider(&data);
6234  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6235
6236  TestCompletionCallback callback;
6237
6238  scoped_ptr<HttpTransaction> trans(
6239      new HttpNetworkTransaction(DEFAULT_PRIORITY,
6240                                 CreateSession(&session_deps_)));
6241
6242  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6243  EXPECT_EQ(ERR_IO_PENDING, rv);
6244
6245  rv = callback.WaitForResult();
6246  EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
6247
6248  rv = trans->RestartIgnoringLastError(callback.callback());
6249  EXPECT_EQ(ERR_IO_PENDING, rv);
6250
6251  rv = callback.WaitForResult();
6252  EXPECT_EQ(OK, rv);
6253
6254  const HttpResponseInfo* response = trans->GetResponseInfo();
6255
6256  ASSERT_TRUE(response != NULL);
6257  EXPECT_EQ(100, response->headers->GetContentLength());
6258}
6259
6260TEST_P(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
6261  HttpRequestInfo request;
6262  request.method = "GET";
6263  request.url = GURL("http://www.google.com/");
6264  request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
6265                                  "Chromium Ultra Awesome X Edition");
6266
6267  scoped_ptr<HttpTransaction> trans(
6268      new HttpNetworkTransaction(DEFAULT_PRIORITY,
6269                                 CreateSession(&session_deps_)));
6270
6271  MockWrite data_writes[] = {
6272    MockWrite("GET / HTTP/1.1\r\n"
6273              "Host: www.google.com\r\n"
6274              "Connection: keep-alive\r\n"
6275              "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
6276  };
6277
6278  // Lastly, the server responds with the actual content.
6279  MockRead data_reads[] = {
6280    MockRead("HTTP/1.0 200 OK\r\n"),
6281    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6282    MockRead("Content-Length: 100\r\n\r\n"),
6283    MockRead(SYNCHRONOUS, OK),
6284  };
6285
6286  StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6287                                data_writes, arraysize(data_writes));
6288  session_deps_.socket_factory->AddSocketDataProvider(&data);
6289
6290  TestCompletionCallback callback;
6291
6292  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6293  EXPECT_EQ(ERR_IO_PENDING, rv);
6294
6295  rv = callback.WaitForResult();
6296  EXPECT_EQ(OK, rv);
6297}
6298
6299TEST_P(HttpNetworkTransactionTest, BuildRequest_UserAgentOverTunnel) {
6300  HttpRequestInfo request;
6301  request.method = "GET";
6302  request.url = GURL("https://www.google.com/");
6303  request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
6304                                  "Chromium Ultra Awesome X Edition");
6305
6306  session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
6307  scoped_ptr<HttpTransaction> trans(
6308      new HttpNetworkTransaction(DEFAULT_PRIORITY,
6309                                 CreateSession(&session_deps_)));
6310
6311  MockWrite data_writes[] = {
6312    MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6313              "Host: www.google.com\r\n"
6314              "Proxy-Connection: keep-alive\r\n"
6315              "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
6316  };
6317  MockRead data_reads[] = {
6318    // Return an error, so the transaction stops here (this test isn't
6319    // interested in the rest).
6320    MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
6321    MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6322    MockRead("Proxy-Connection: close\r\n\r\n"),
6323  };
6324
6325  StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6326                                data_writes, arraysize(data_writes));
6327  session_deps_.socket_factory->AddSocketDataProvider(&data);
6328
6329  TestCompletionCallback callback;
6330
6331  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6332  EXPECT_EQ(ERR_IO_PENDING, rv);
6333
6334  rv = callback.WaitForResult();
6335  EXPECT_EQ(OK, rv);
6336}
6337
6338TEST_P(HttpNetworkTransactionTest, BuildRequest_Referer) {
6339  HttpRequestInfo request;
6340  request.method = "GET";
6341  request.url = GURL("http://www.google.com/");
6342  request.load_flags = 0;
6343  request.extra_headers.SetHeader(HttpRequestHeaders::kReferer,
6344                                  "http://the.previous.site.com/");
6345
6346  scoped_ptr<HttpTransaction> trans(
6347      new HttpNetworkTransaction(DEFAULT_PRIORITY,
6348                                 CreateSession(&session_deps_)));
6349
6350  MockWrite data_writes[] = {
6351    MockWrite("GET / HTTP/1.1\r\n"
6352              "Host: www.google.com\r\n"
6353              "Connection: keep-alive\r\n"
6354              "Referer: http://the.previous.site.com/\r\n\r\n"),
6355  };
6356
6357  // Lastly, the server responds with the actual content.
6358  MockRead data_reads[] = {
6359    MockRead("HTTP/1.0 200 OK\r\n"),
6360    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6361    MockRead("Content-Length: 100\r\n\r\n"),
6362    MockRead(SYNCHRONOUS, OK),
6363  };
6364
6365  StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6366                                data_writes, arraysize(data_writes));
6367  session_deps_.socket_factory->AddSocketDataProvider(&data);
6368
6369  TestCompletionCallback callback;
6370
6371  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6372  EXPECT_EQ(ERR_IO_PENDING, rv);
6373
6374  rv = callback.WaitForResult();
6375  EXPECT_EQ(OK, rv);
6376}
6377
6378TEST_P(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
6379  HttpRequestInfo request;
6380  request.method = "POST";
6381  request.url = GURL("http://www.google.com/");
6382
6383  scoped_ptr<HttpTransaction> trans(
6384      new HttpNetworkTransaction(DEFAULT_PRIORITY,
6385                                 CreateSession(&session_deps_)));
6386
6387  MockWrite data_writes[] = {
6388    MockWrite("POST / HTTP/1.1\r\n"
6389              "Host: www.google.com\r\n"
6390              "Connection: keep-alive\r\n"
6391              "Content-Length: 0\r\n\r\n"),
6392  };
6393
6394  // Lastly, the server responds with the actual content.
6395  MockRead data_reads[] = {
6396    MockRead("HTTP/1.0 200 OK\r\n"),
6397    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6398    MockRead("Content-Length: 100\r\n\r\n"),
6399    MockRead(SYNCHRONOUS, OK),
6400  };
6401
6402  StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6403                                data_writes, arraysize(data_writes));
6404  session_deps_.socket_factory->AddSocketDataProvider(&data);
6405
6406  TestCompletionCallback callback;
6407
6408  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6409  EXPECT_EQ(ERR_IO_PENDING, rv);
6410
6411  rv = callback.WaitForResult();
6412  EXPECT_EQ(OK, rv);
6413}
6414
6415TEST_P(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
6416  HttpRequestInfo request;
6417  request.method = "PUT";
6418  request.url = GURL("http://www.google.com/");
6419
6420  scoped_ptr<HttpTransaction> trans(
6421      new HttpNetworkTransaction(DEFAULT_PRIORITY,
6422                                 CreateSession(&session_deps_)));
6423
6424  MockWrite data_writes[] = {
6425    MockWrite("PUT / HTTP/1.1\r\n"
6426              "Host: www.google.com\r\n"
6427              "Connection: keep-alive\r\n"
6428              "Content-Length: 0\r\n\r\n"),
6429  };
6430
6431  // Lastly, the server responds with the actual content.
6432  MockRead data_reads[] = {
6433    MockRead("HTTP/1.0 200 OK\r\n"),
6434    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6435    MockRead("Content-Length: 100\r\n\r\n"),
6436    MockRead(SYNCHRONOUS, OK),
6437  };
6438
6439  StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6440                                data_writes, arraysize(data_writes));
6441  session_deps_.socket_factory->AddSocketDataProvider(&data);
6442
6443  TestCompletionCallback callback;
6444
6445  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6446  EXPECT_EQ(ERR_IO_PENDING, rv);
6447
6448  rv = callback.WaitForResult();
6449  EXPECT_EQ(OK, rv);
6450}
6451
6452TEST_P(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
6453  HttpRequestInfo request;
6454  request.method = "HEAD";
6455  request.url = GURL("http://www.google.com/");
6456
6457  scoped_ptr<HttpTransaction> trans(
6458      new HttpNetworkTransaction(DEFAULT_PRIORITY,
6459                                 CreateSession(&session_deps_)));
6460
6461  MockWrite data_writes[] = {
6462    MockWrite("HEAD / HTTP/1.1\r\n"
6463              "Host: www.google.com\r\n"
6464              "Connection: keep-alive\r\n"
6465              "Content-Length: 0\r\n\r\n"),
6466  };
6467
6468  // Lastly, the server responds with the actual content.
6469  MockRead data_reads[] = {
6470    MockRead("HTTP/1.0 200 OK\r\n"),
6471    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6472    MockRead("Content-Length: 100\r\n\r\n"),
6473    MockRead(SYNCHRONOUS, OK),
6474  };
6475
6476  StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6477                                data_writes, arraysize(data_writes));
6478  session_deps_.socket_factory->AddSocketDataProvider(&data);
6479
6480  TestCompletionCallback callback;
6481
6482  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6483  EXPECT_EQ(ERR_IO_PENDING, rv);
6484
6485  rv = callback.WaitForResult();
6486  EXPECT_EQ(OK, rv);
6487}
6488
6489TEST_P(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
6490  HttpRequestInfo request;
6491  request.method = "GET";
6492  request.url = GURL("http://www.google.com/");
6493  request.load_flags = LOAD_BYPASS_CACHE;
6494
6495  scoped_ptr<HttpTransaction> trans(
6496      new HttpNetworkTransaction(DEFAULT_PRIORITY,
6497                                 CreateSession(&session_deps_)));
6498
6499  MockWrite data_writes[] = {
6500    MockWrite("GET / HTTP/1.1\r\n"
6501              "Host: www.google.com\r\n"
6502              "Connection: keep-alive\r\n"
6503              "Pragma: no-cache\r\n"
6504              "Cache-Control: no-cache\r\n\r\n"),
6505  };
6506
6507  // Lastly, the server responds with the actual content.
6508  MockRead data_reads[] = {
6509    MockRead("HTTP/1.0 200 OK\r\n"),
6510    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6511    MockRead("Content-Length: 100\r\n\r\n"),
6512    MockRead(SYNCHRONOUS, OK),
6513  };
6514
6515  StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6516                                data_writes, arraysize(data_writes));
6517  session_deps_.socket_factory->AddSocketDataProvider(&data);
6518
6519  TestCompletionCallback callback;
6520
6521  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6522  EXPECT_EQ(ERR_IO_PENDING, rv);
6523
6524  rv = callback.WaitForResult();
6525  EXPECT_EQ(OK, rv);
6526}
6527
6528TEST_P(HttpNetworkTransactionTest,
6529       BuildRequest_CacheControlValidateCache) {
6530  HttpRequestInfo request;
6531  request.method = "GET";
6532  request.url = GURL("http://www.google.com/");
6533  request.load_flags = LOAD_VALIDATE_CACHE;
6534
6535  scoped_ptr<HttpTransaction> trans(
6536      new HttpNetworkTransaction(DEFAULT_PRIORITY,
6537                                 CreateSession(&session_deps_)));
6538
6539  MockWrite data_writes[] = {
6540    MockWrite("GET / HTTP/1.1\r\n"
6541              "Host: www.google.com\r\n"
6542              "Connection: keep-alive\r\n"
6543              "Cache-Control: max-age=0\r\n\r\n"),
6544  };
6545
6546  // Lastly, the server responds with the actual content.
6547  MockRead data_reads[] = {
6548    MockRead("HTTP/1.0 200 OK\r\n"),
6549    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6550    MockRead("Content-Length: 100\r\n\r\n"),
6551    MockRead(SYNCHRONOUS, OK),
6552  };
6553
6554  StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6555                                data_writes, arraysize(data_writes));
6556  session_deps_.socket_factory->AddSocketDataProvider(&data);
6557
6558  TestCompletionCallback callback;
6559
6560  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6561  EXPECT_EQ(ERR_IO_PENDING, rv);
6562
6563  rv = callback.WaitForResult();
6564  EXPECT_EQ(OK, rv);
6565}
6566
6567TEST_P(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
6568  HttpRequestInfo request;
6569  request.method = "GET";
6570  request.url = GURL("http://www.google.com/");
6571  request.extra_headers.SetHeader("FooHeader", "Bar");
6572
6573  scoped_ptr<HttpTransaction> trans(
6574      new HttpNetworkTransaction(DEFAULT_PRIORITY,
6575                                 CreateSession(&session_deps_)));
6576
6577  MockWrite data_writes[] = {
6578    MockWrite("GET / HTTP/1.1\r\n"
6579              "Host: www.google.com\r\n"
6580              "Connection: keep-alive\r\n"
6581              "FooHeader: Bar\r\n\r\n"),
6582  };
6583
6584  // Lastly, the server responds with the actual content.
6585  MockRead data_reads[] = {
6586    MockRead("HTTP/1.0 200 OK\r\n"),
6587    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6588    MockRead("Content-Length: 100\r\n\r\n"),
6589    MockRead(SYNCHRONOUS, OK),
6590  };
6591
6592  StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6593                                data_writes, arraysize(data_writes));
6594  session_deps_.socket_factory->AddSocketDataProvider(&data);
6595
6596  TestCompletionCallback callback;
6597
6598  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6599  EXPECT_EQ(ERR_IO_PENDING, rv);
6600
6601  rv = callback.WaitForResult();
6602  EXPECT_EQ(OK, rv);
6603}
6604
6605TEST_P(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) {
6606  HttpRequestInfo request;
6607  request.method = "GET";
6608  request.url = GURL("http://www.google.com/");
6609  request.extra_headers.SetHeader("referer", "www.foo.com");
6610  request.extra_headers.SetHeader("hEllo", "Kitty");
6611  request.extra_headers.SetHeader("FoO", "bar");
6612
6613  scoped_ptr<HttpTransaction> trans(
6614      new HttpNetworkTransaction(DEFAULT_PRIORITY,
6615                                 CreateSession(&session_deps_)));
6616
6617  MockWrite data_writes[] = {
6618    MockWrite("GET / HTTP/1.1\r\n"
6619              "Host: www.google.com\r\n"
6620              "Connection: keep-alive\r\n"
6621              "referer: www.foo.com\r\n"
6622              "hEllo: Kitty\r\n"
6623              "FoO: bar\r\n\r\n"),
6624  };
6625
6626  // Lastly, the server responds with the actual content.
6627  MockRead data_reads[] = {
6628    MockRead("HTTP/1.0 200 OK\r\n"),
6629    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6630    MockRead("Content-Length: 100\r\n\r\n"),
6631    MockRead(SYNCHRONOUS, OK),
6632  };
6633
6634  StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6635                                data_writes, arraysize(data_writes));
6636  session_deps_.socket_factory->AddSocketDataProvider(&data);
6637
6638  TestCompletionCallback callback;
6639
6640  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6641  EXPECT_EQ(ERR_IO_PENDING, rv);
6642
6643  rv = callback.WaitForResult();
6644  EXPECT_EQ(OK, rv);
6645}
6646
6647TEST_P(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
6648  HttpRequestInfo request;
6649  request.method = "GET";
6650  request.url = GURL("http://www.google.com/");
6651  request.load_flags = 0;
6652
6653  session_deps_.proxy_service.reset(
6654      ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080"));
6655  CapturingNetLog net_log;
6656  session_deps_.net_log = &net_log;
6657
6658  scoped_ptr<HttpTransaction> trans(
6659      new HttpNetworkTransaction(DEFAULT_PRIORITY,
6660                                 CreateSession(&session_deps_)));
6661
6662  char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
6663  char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
6664
6665  MockWrite data_writes[] = {
6666    MockWrite(ASYNC, write_buffer, arraysize(write_buffer)),
6667    MockWrite("GET / HTTP/1.1\r\n"
6668              "Host: www.google.com\r\n"
6669              "Connection: keep-alive\r\n\r\n")
6670  };
6671
6672  MockRead data_reads[] = {
6673    MockRead(ASYNC, read_buffer, arraysize(read_buffer)),
6674    MockRead("HTTP/1.0 200 OK\r\n"),
6675    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
6676    MockRead("Payload"),
6677    MockRead(SYNCHRONOUS, OK)
6678  };
6679
6680  StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6681                                data_writes, arraysize(data_writes));
6682  session_deps_.socket_factory->AddSocketDataProvider(&data);
6683
6684  TestCompletionCallback callback;
6685
6686  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6687  EXPECT_EQ(ERR_IO_PENDING, rv);
6688
6689  rv = callback.WaitForResult();
6690  EXPECT_EQ(OK, rv);
6691
6692  const HttpResponseInfo* response = trans->GetResponseInfo();
6693  ASSERT_TRUE(response != NULL);
6694
6695  LoadTimingInfo load_timing_info;
6696  EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
6697  TestLoadTimingNotReusedWithPac(load_timing_info,
6698                                 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
6699
6700  std::string response_text;
6701  rv = ReadTransaction(trans.get(), &response_text);
6702  EXPECT_EQ(OK, rv);
6703  EXPECT_EQ("Payload", response_text);
6704}
6705
6706TEST_P(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
6707  HttpRequestInfo request;
6708  request.method = "GET";
6709  request.url = GURL("https://www.google.com/");
6710  request.load_flags = 0;
6711
6712  session_deps_.proxy_service.reset(
6713      ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080"));
6714  CapturingNetLog net_log;
6715  session_deps_.net_log = &net_log;
6716
6717  scoped_ptr<HttpTransaction> trans(
6718      new HttpNetworkTransaction(DEFAULT_PRIORITY,
6719                                 CreateSession(&session_deps_)));
6720
6721  unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
6722  unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
6723
6724  MockWrite data_writes[] = {
6725    MockWrite(ASYNC, reinterpret_cast<char*>(write_buffer),
6726              arraysize(write_buffer)),
6727    MockWrite("GET / HTTP/1.1\r\n"
6728              "Host: www.google.com\r\n"
6729              "Connection: keep-alive\r\n\r\n")
6730  };
6731
6732  MockRead data_reads[] = {
6733    MockRead(ASYNC, reinterpret_cast<char*>(read_buffer),
6734             arraysize(read_buffer)),
6735    MockRead("HTTP/1.0 200 OK\r\n"),
6736    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
6737    MockRead("Payload"),
6738    MockRead(SYNCHRONOUS, OK)
6739  };
6740
6741  StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6742                                data_writes, arraysize(data_writes));
6743  session_deps_.socket_factory->AddSocketDataProvider(&data);
6744
6745  SSLSocketDataProvider ssl(ASYNC, OK);
6746  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6747
6748  TestCompletionCallback callback;
6749
6750  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6751  EXPECT_EQ(ERR_IO_PENDING, rv);
6752
6753  rv = callback.WaitForResult();
6754  EXPECT_EQ(OK, rv);
6755
6756  LoadTimingInfo load_timing_info;
6757  EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
6758  TestLoadTimingNotReusedWithPac(load_timing_info,
6759                                 CONNECT_TIMING_HAS_SSL_TIMES);
6760
6761  const HttpResponseInfo* response = trans->GetResponseInfo();
6762  ASSERT_TRUE(response != NULL);
6763
6764  std::string response_text;
6765  rv = ReadTransaction(trans.get(), &response_text);
6766  EXPECT_EQ(OK, rv);
6767  EXPECT_EQ("Payload", response_text);
6768}
6769
6770TEST_P(HttpNetworkTransactionTest, SOCKS4_HTTP_GET_no_PAC) {
6771  HttpRequestInfo request;
6772  request.method = "GET";
6773  request.url = GURL("http://www.google.com/");
6774  request.load_flags = 0;
6775
6776  session_deps_.proxy_service.reset(
6777      ProxyService::CreateFixed("socks4://myproxy:1080"));
6778  CapturingNetLog net_log;
6779  session_deps_.net_log = &net_log;
6780
6781  scoped_ptr<HttpTransaction> trans(
6782      new HttpNetworkTransaction(DEFAULT_PRIORITY,
6783                                 CreateSession(&session_deps_)));
6784
6785  char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
6786  char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
6787
6788  MockWrite data_writes[] = {
6789    MockWrite(ASYNC, write_buffer, arraysize(write_buffer)),
6790    MockWrite("GET / HTTP/1.1\r\n"
6791              "Host: www.google.com\r\n"
6792              "Connection: keep-alive\r\n\r\n")
6793  };
6794
6795  MockRead data_reads[] = {
6796    MockRead(ASYNC, read_buffer, arraysize(read_buffer)),
6797    MockRead("HTTP/1.0 200 OK\r\n"),
6798    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
6799    MockRead("Payload"),
6800    MockRead(SYNCHRONOUS, OK)
6801  };
6802
6803  StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6804                                data_writes, arraysize(data_writes));
6805  session_deps_.socket_factory->AddSocketDataProvider(&data);
6806
6807  TestCompletionCallback callback;
6808
6809  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6810  EXPECT_EQ(ERR_IO_PENDING, rv);
6811
6812  rv = callback.WaitForResult();
6813  EXPECT_EQ(OK, rv);
6814
6815  const HttpResponseInfo* response = trans->GetResponseInfo();
6816  ASSERT_TRUE(response != NULL);
6817
6818  LoadTimingInfo load_timing_info;
6819  EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
6820  TestLoadTimingNotReused(load_timing_info,
6821                          CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
6822
6823  std::string response_text;
6824  rv = ReadTransaction(trans.get(), &response_text);
6825  EXPECT_EQ(OK, rv);
6826  EXPECT_EQ("Payload", response_text);
6827}
6828
6829TEST_P(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
6830  HttpRequestInfo request;
6831  request.method = "GET";
6832  request.url = GURL("http://www.google.com/");
6833  request.load_flags = 0;
6834
6835  session_deps_.proxy_service.reset(
6836      ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080"));
6837  CapturingNetLog net_log;
6838  session_deps_.net_log = &net_log;
6839
6840  scoped_ptr<HttpTransaction> trans(
6841      new HttpNetworkTransaction(DEFAULT_PRIORITY,
6842                                 CreateSession(&session_deps_)));
6843
6844  const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
6845  const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
6846  const char kSOCKS5OkRequest[] = {
6847    0x05,  // Version
6848    0x01,  // Command (CONNECT)
6849    0x00,  // Reserved.
6850    0x03,  // Address type (DOMAINNAME).
6851    0x0E,  // Length of domain (14)
6852    // Domain string:
6853    'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
6854    0x00, 0x50,  // 16-bit port (80)
6855  };
6856  const char kSOCKS5OkResponse[] =
6857      { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
6858
6859  MockWrite data_writes[] = {
6860    MockWrite(ASYNC, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
6861    MockWrite(ASYNC, kSOCKS5OkRequest, arraysize(kSOCKS5OkRequest)),
6862    MockWrite("GET / HTTP/1.1\r\n"
6863              "Host: www.google.com\r\n"
6864              "Connection: keep-alive\r\n\r\n")
6865  };
6866
6867  MockRead data_reads[] = {
6868    MockRead(ASYNC, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
6869    MockRead(ASYNC, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
6870    MockRead("HTTP/1.0 200 OK\r\n"),
6871    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
6872    MockRead("Payload"),
6873    MockRead(SYNCHRONOUS, OK)
6874  };
6875
6876  StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6877                                data_writes, arraysize(data_writes));
6878  session_deps_.socket_factory->AddSocketDataProvider(&data);
6879
6880  TestCompletionCallback callback;
6881
6882  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6883  EXPECT_EQ(ERR_IO_PENDING, rv);
6884
6885  rv = callback.WaitForResult();
6886  EXPECT_EQ(OK, rv);
6887
6888  const HttpResponseInfo* response = trans->GetResponseInfo();
6889  ASSERT_TRUE(response != NULL);
6890
6891  LoadTimingInfo load_timing_info;
6892  EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
6893  TestLoadTimingNotReusedWithPac(load_timing_info,
6894                                 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
6895
6896  std::string response_text;
6897  rv = ReadTransaction(trans.get(), &response_text);
6898  EXPECT_EQ(OK, rv);
6899  EXPECT_EQ("Payload", response_text);
6900}
6901
6902TEST_P(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
6903  HttpRequestInfo request;
6904  request.method = "GET";
6905  request.url = GURL("https://www.google.com/");
6906  request.load_flags = 0;
6907
6908  session_deps_.proxy_service.reset(
6909      ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080"));
6910  CapturingNetLog net_log;
6911  session_deps_.net_log = &net_log;
6912
6913  scoped_ptr<HttpTransaction> trans(
6914      new HttpNetworkTransaction(DEFAULT_PRIORITY,
6915                                 CreateSession(&session_deps_)));
6916
6917  const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
6918  const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
6919  const unsigned char kSOCKS5OkRequest[] = {
6920    0x05,  // Version
6921    0x01,  // Command (CONNECT)
6922    0x00,  // Reserved.
6923    0x03,  // Address type (DOMAINNAME).
6924    0x0E,  // Length of domain (14)
6925    // Domain string:
6926    'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
6927    0x01, 0xBB,  // 16-bit port (443)
6928  };
6929
6930  const char kSOCKS5OkResponse[] =
6931      { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
6932
6933  MockWrite data_writes[] = {
6934    MockWrite(ASYNC, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
6935    MockWrite(ASYNC, reinterpret_cast<const char*>(kSOCKS5OkRequest),
6936              arraysize(kSOCKS5OkRequest)),
6937    MockWrite("GET / HTTP/1.1\r\n"
6938              "Host: www.google.com\r\n"
6939              "Connection: keep-alive\r\n\r\n")
6940  };
6941
6942  MockRead data_reads[] = {
6943    MockRead(ASYNC, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
6944    MockRead(ASYNC, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
6945    MockRead("HTTP/1.0 200 OK\r\n"),
6946    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
6947    MockRead("Payload"),
6948    MockRead(SYNCHRONOUS, OK)
6949  };
6950
6951  StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6952                                data_writes, arraysize(data_writes));
6953  session_deps_.socket_factory->AddSocketDataProvider(&data);
6954
6955  SSLSocketDataProvider ssl(ASYNC, OK);
6956  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6957
6958  TestCompletionCallback callback;
6959
6960  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6961  EXPECT_EQ(ERR_IO_PENDING, rv);
6962
6963  rv = callback.WaitForResult();
6964  EXPECT_EQ(OK, rv);
6965
6966  const HttpResponseInfo* response = trans->GetResponseInfo();
6967  ASSERT_TRUE(response != NULL);
6968
6969  LoadTimingInfo load_timing_info;
6970  EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
6971  TestLoadTimingNotReusedWithPac(load_timing_info,
6972                                 CONNECT_TIMING_HAS_SSL_TIMES);
6973
6974  std::string response_text;
6975  rv = ReadTransaction(trans.get(), &response_text);
6976  EXPECT_EQ(OK, rv);
6977  EXPECT_EQ("Payload", response_text);
6978}
6979
6980namespace {
6981
6982// Tests that for connection endpoints the group names are correctly set.
6983
6984struct GroupNameTest {
6985  std::string proxy_server;
6986  std::string url;
6987  std::string expected_group_name;
6988  bool ssl;
6989};
6990
6991scoped_refptr<HttpNetworkSession> SetupSessionForGroupNameTests(
6992    NextProto next_proto,
6993    SpdySessionDependencies* session_deps_) {
6994  scoped_refptr<HttpNetworkSession> session(CreateSession(session_deps_));
6995
6996  base::WeakPtr<HttpServerProperties> http_server_properties =
6997      session->http_server_properties();
6998  http_server_properties->SetAlternateProtocol(
6999      HostPortPair("host.with.alternate", 80), 443,
7000      AlternateProtocolFromNextProto(next_proto));
7001
7002  return session;
7003}
7004
7005int GroupNameTransactionHelper(
7006    const std::string& url,
7007    const scoped_refptr<HttpNetworkSession>& session) {
7008  HttpRequestInfo request;
7009  request.method = "GET";
7010  request.url = GURL(url);
7011  request.load_flags = 0;
7012
7013  scoped_ptr<HttpTransaction> trans(
7014      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7015
7016  TestCompletionCallback callback;
7017
7018  // We do not complete this request, the dtor will clean the transaction up.
7019  return trans->Start(&request, callback.callback(), BoundNetLog());
7020}
7021
7022}  // namespace
7023
7024TEST_P(HttpNetworkTransactionTest, GroupNameForDirectConnections) {
7025  const GroupNameTest tests[] = {
7026    {
7027      "",  // unused
7028      "http://www.google.com/direct",
7029      "www.google.com:80",
7030      false,
7031    },
7032    {
7033      "",  // unused
7034      "http://[2001:1418:13:1::25]/direct",
7035      "[2001:1418:13:1::25]:80",
7036      false,
7037    },
7038
7039    // SSL Tests
7040    {
7041      "",  // unused
7042      "https://www.google.com/direct_ssl",
7043      "ssl/www.google.com:443",
7044      true,
7045    },
7046    {
7047      "",  // unused
7048      "https://[2001:1418:13:1::25]/direct",
7049      "ssl/[2001:1418:13:1::25]:443",
7050      true,
7051    },
7052    {
7053      "",  // unused
7054      "http://host.with.alternate/direct",
7055      "ssl/host.with.alternate:443",
7056      true,
7057    },
7058  };
7059
7060  HttpStreamFactory::set_use_alternate_protocols(true);
7061
7062  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
7063    session_deps_.proxy_service.reset(
7064        ProxyService::CreateFixed(tests[i].proxy_server));
7065    scoped_refptr<HttpNetworkSession> session(
7066        SetupSessionForGroupNameTests(GetParam(), &session_deps_));
7067
7068    HttpNetworkSessionPeer peer(session);
7069    CaptureGroupNameTransportSocketPool* transport_conn_pool =
7070        new CaptureGroupNameTransportSocketPool(NULL, NULL);
7071    CaptureGroupNameSSLSocketPool* ssl_conn_pool =
7072        new CaptureGroupNameSSLSocketPool(NULL, NULL);
7073    MockClientSocketPoolManager* mock_pool_manager =
7074        new MockClientSocketPoolManager;
7075    mock_pool_manager->SetTransportSocketPool(transport_conn_pool);
7076    mock_pool_manager->SetSSLSocketPool(ssl_conn_pool);
7077    peer.SetClientSocketPoolManager(mock_pool_manager);
7078
7079    EXPECT_EQ(ERR_IO_PENDING,
7080              GroupNameTransactionHelper(tests[i].url, session));
7081    if (tests[i].ssl)
7082      EXPECT_EQ(tests[i].expected_group_name,
7083                ssl_conn_pool->last_group_name_received());
7084    else
7085      EXPECT_EQ(tests[i].expected_group_name,
7086                transport_conn_pool->last_group_name_received());
7087  }
7088
7089}
7090
7091TEST_P(HttpNetworkTransactionTest, GroupNameForHTTPProxyConnections) {
7092  const GroupNameTest tests[] = {
7093    {
7094      "http_proxy",
7095      "http://www.google.com/http_proxy_normal",
7096      "www.google.com:80",
7097      false,
7098    },
7099
7100    // SSL Tests
7101    {
7102      "http_proxy",
7103      "https://www.google.com/http_connect_ssl",
7104      "ssl/www.google.com:443",
7105      true,
7106    },
7107
7108    {
7109      "http_proxy",
7110      "http://host.with.alternate/direct",
7111      "ssl/host.with.alternate:443",
7112      true,
7113    },
7114
7115    {
7116      "http_proxy",
7117      "ftp://ftp.google.com/http_proxy_normal",
7118      "ftp/ftp.google.com:21",
7119      false,
7120    },
7121  };
7122
7123  HttpStreamFactory::set_use_alternate_protocols(true);
7124
7125  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
7126    session_deps_.proxy_service.reset(
7127        ProxyService::CreateFixed(tests[i].proxy_server));
7128    scoped_refptr<HttpNetworkSession> session(
7129        SetupSessionForGroupNameTests(GetParam(), &session_deps_));
7130
7131    HttpNetworkSessionPeer peer(session);
7132
7133    HostPortPair proxy_host("http_proxy", 80);
7134    CaptureGroupNameHttpProxySocketPool* http_proxy_pool =
7135        new CaptureGroupNameHttpProxySocketPool(NULL, NULL);
7136    CaptureGroupNameSSLSocketPool* ssl_conn_pool =
7137        new CaptureGroupNameSSLSocketPool(NULL, NULL);
7138
7139    MockClientSocketPoolManager* mock_pool_manager =
7140        new MockClientSocketPoolManager;
7141    mock_pool_manager->SetSocketPoolForHTTPProxy(proxy_host, http_proxy_pool);
7142    mock_pool_manager->SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
7143    peer.SetClientSocketPoolManager(mock_pool_manager);
7144
7145    EXPECT_EQ(ERR_IO_PENDING,
7146              GroupNameTransactionHelper(tests[i].url, session));
7147    if (tests[i].ssl)
7148      EXPECT_EQ(tests[i].expected_group_name,
7149                ssl_conn_pool->last_group_name_received());
7150    else
7151      EXPECT_EQ(tests[i].expected_group_name,
7152                http_proxy_pool->last_group_name_received());
7153  }
7154}
7155
7156TEST_P(HttpNetworkTransactionTest, GroupNameForSOCKSConnections) {
7157  const GroupNameTest tests[] = {
7158    {
7159      "socks4://socks_proxy:1080",
7160      "http://www.google.com/socks4_direct",
7161      "socks4/www.google.com:80",
7162      false,
7163    },
7164    {
7165      "socks5://socks_proxy:1080",
7166      "http://www.google.com/socks5_direct",
7167      "socks5/www.google.com:80",
7168      false,
7169    },
7170
7171    // SSL Tests
7172    {
7173      "socks4://socks_proxy:1080",
7174      "https://www.google.com/socks4_ssl",
7175      "socks4/ssl/www.google.com:443",
7176      true,
7177    },
7178    {
7179      "socks5://socks_proxy:1080",
7180      "https://www.google.com/socks5_ssl",
7181      "socks5/ssl/www.google.com:443",
7182      true,
7183    },
7184
7185    {
7186      "socks4://socks_proxy:1080",
7187      "http://host.with.alternate/direct",
7188      "socks4/ssl/host.with.alternate:443",
7189      true,
7190    },
7191  };
7192
7193  HttpStreamFactory::set_use_alternate_protocols(true);
7194
7195  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
7196    session_deps_.proxy_service.reset(
7197        ProxyService::CreateFixed(tests[i].proxy_server));
7198    scoped_refptr<HttpNetworkSession> session(
7199        SetupSessionForGroupNameTests(GetParam(), &session_deps_));
7200
7201    HttpNetworkSessionPeer peer(session);
7202
7203    HostPortPair proxy_host("socks_proxy", 1080);
7204    CaptureGroupNameSOCKSSocketPool* socks_conn_pool =
7205        new CaptureGroupNameSOCKSSocketPool(NULL, NULL);
7206    CaptureGroupNameSSLSocketPool* ssl_conn_pool =
7207        new CaptureGroupNameSSLSocketPool(NULL, NULL);
7208
7209    MockClientSocketPoolManager* mock_pool_manager =
7210        new MockClientSocketPoolManager;
7211    mock_pool_manager->SetSocketPoolForSOCKSProxy(proxy_host, socks_conn_pool);
7212    mock_pool_manager->SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
7213    peer.SetClientSocketPoolManager(mock_pool_manager);
7214
7215    scoped_ptr<HttpTransaction> trans(
7216        new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7217
7218    EXPECT_EQ(ERR_IO_PENDING,
7219              GroupNameTransactionHelper(tests[i].url, session));
7220    if (tests[i].ssl)
7221      EXPECT_EQ(tests[i].expected_group_name,
7222                ssl_conn_pool->last_group_name_received());
7223    else
7224      EXPECT_EQ(tests[i].expected_group_name,
7225                socks_conn_pool->last_group_name_received());
7226  }
7227}
7228
7229TEST_P(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
7230  HttpRequestInfo request;
7231  request.method = "GET";
7232  request.url = GURL("http://www.google.com/");
7233
7234  session_deps_.proxy_service.reset(
7235      ProxyService::CreateFixed("myproxy:70;foobar:80"));
7236
7237  // This simulates failure resolving all hostnames; that means we will fail
7238  // connecting to both proxies (myproxy:70 and foobar:80).
7239  session_deps_.host_resolver->rules()->AddSimulatedFailure("*");
7240
7241  scoped_ptr<HttpTransaction> trans(
7242      new HttpNetworkTransaction(DEFAULT_PRIORITY,
7243                                 CreateSession(&session_deps_)));
7244
7245  TestCompletionCallback callback;
7246
7247  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7248  EXPECT_EQ(ERR_IO_PENDING, rv);
7249
7250  rv = callback.WaitForResult();
7251  EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED, rv);
7252}
7253
7254// Base test to make sure that when the load flags for a request specify to
7255// bypass the cache, the DNS cache is not used.
7256void HttpNetworkTransactionTest::BypassHostCacheOnRefreshHelper(
7257    int load_flags) {
7258  // Issue a request, asking to bypass the cache(s).
7259  HttpRequestInfo request;
7260  request.method = "GET";
7261  request.load_flags = load_flags;
7262  request.url = GURL("http://www.google.com/");
7263
7264  // Select a host resolver that does caching.
7265  session_deps_.host_resolver.reset(new MockCachingHostResolver);
7266
7267  scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(DEFAULT_PRIORITY,
7268      CreateSession(&session_deps_)));
7269
7270  // Warm up the host cache so it has an entry for "www.google.com".
7271  AddressList addrlist;
7272  TestCompletionCallback callback;
7273  int rv = session_deps_.host_resolver->Resolve(
7274      HostResolver::RequestInfo(HostPortPair("www.google.com", 80)), &addrlist,
7275      callback.callback(), NULL, BoundNetLog());
7276  EXPECT_EQ(ERR_IO_PENDING, rv);
7277  rv = callback.WaitForResult();
7278  EXPECT_EQ(OK, rv);
7279
7280  // Verify that it was added to host cache, by doing a subsequent async lookup
7281  // and confirming it completes synchronously.
7282  rv = session_deps_.host_resolver->Resolve(
7283      HostResolver::RequestInfo(HostPortPair("www.google.com", 80)), &addrlist,
7284      callback.callback(), NULL, BoundNetLog());
7285  ASSERT_EQ(OK, rv);
7286
7287  // Inject a failure the next time that "www.google.com" is resolved. This way
7288  // we can tell if the next lookup hit the cache, or the "network".
7289  // (cache --> success, "network" --> failure).
7290  session_deps_.host_resolver->rules()->AddSimulatedFailure("www.google.com");
7291
7292  // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
7293  // first read -- this won't be reached as the host resolution will fail first.
7294  MockRead data_reads[] = { MockRead(SYNCHRONOUS, ERR_UNEXPECTED) };
7295  StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
7296  session_deps_.socket_factory->AddSocketDataProvider(&data);
7297
7298  // Run the request.
7299  rv = trans->Start(&request, callback.callback(), BoundNetLog());
7300  ASSERT_EQ(ERR_IO_PENDING, rv);
7301  rv = callback.WaitForResult();
7302
7303  // If we bypassed the cache, we would have gotten a failure while resolving
7304  // "www.google.com".
7305  EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
7306}
7307
7308// There are multiple load flags that should trigger the host cache bypass.
7309// Test each in isolation:
7310TEST_P(HttpNetworkTransactionTest, BypassHostCacheOnRefresh1) {
7311  BypassHostCacheOnRefreshHelper(LOAD_BYPASS_CACHE);
7312}
7313
7314TEST_P(HttpNetworkTransactionTest, BypassHostCacheOnRefresh2) {
7315  BypassHostCacheOnRefreshHelper(LOAD_VALIDATE_CACHE);
7316}
7317
7318TEST_P(HttpNetworkTransactionTest, BypassHostCacheOnRefresh3) {
7319  BypassHostCacheOnRefreshHelper(LOAD_DISABLE_CACHE);
7320}
7321
7322// Make sure we can handle an error when writing the request.
7323TEST_P(HttpNetworkTransactionTest, RequestWriteError) {
7324  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7325
7326  HttpRequestInfo request;
7327  request.method = "GET";
7328  request.url = GURL("http://www.foo.com/");
7329  request.load_flags = 0;
7330
7331  MockWrite write_failure[] = {
7332    MockWrite(ASYNC, ERR_CONNECTION_RESET),
7333  };
7334  StaticSocketDataProvider data(NULL, 0,
7335                                write_failure, arraysize(write_failure));
7336  session_deps_.socket_factory->AddSocketDataProvider(&data);
7337
7338  TestCompletionCallback callback;
7339
7340  scoped_ptr<HttpTransaction> trans(
7341      new HttpNetworkTransaction(DEFAULT_PRIORITY,
7342                                 CreateSession(&session_deps_)));
7343
7344  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7345  EXPECT_EQ(ERR_IO_PENDING, rv);
7346
7347  rv = callback.WaitForResult();
7348  EXPECT_EQ(ERR_CONNECTION_RESET, rv);
7349}
7350
7351// Check that a connection closed after the start of the headers finishes ok.
7352TEST_P(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
7353  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7354
7355  HttpRequestInfo request;
7356  request.method = "GET";
7357  request.url = GURL("http://www.foo.com/");
7358  request.load_flags = 0;
7359
7360  MockRead data_reads[] = {
7361    MockRead("HTTP/1."),
7362    MockRead(SYNCHRONOUS, OK),
7363  };
7364
7365  StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
7366  session_deps_.socket_factory->AddSocketDataProvider(&data);
7367
7368  TestCompletionCallback callback;
7369
7370  scoped_ptr<HttpTransaction> trans(
7371      new HttpNetworkTransaction(DEFAULT_PRIORITY,
7372                                 CreateSession(&session_deps_)));
7373
7374  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7375  EXPECT_EQ(ERR_IO_PENDING, rv);
7376
7377  rv = callback.WaitForResult();
7378  EXPECT_EQ(OK, rv);
7379
7380  const HttpResponseInfo* response = trans->GetResponseInfo();
7381  ASSERT_TRUE(response != NULL);
7382
7383  EXPECT_TRUE(response->headers.get() != NULL);
7384  EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
7385
7386  std::string response_data;
7387  rv = ReadTransaction(trans.get(), &response_data);
7388  EXPECT_EQ(OK, rv);
7389  EXPECT_EQ("", response_data);
7390}
7391
7392// Make sure that a dropped connection while draining the body for auth
7393// restart does the right thing.
7394TEST_P(HttpNetworkTransactionTest, DrainResetOK) {
7395  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7396
7397  HttpRequestInfo request;
7398  request.method = "GET";
7399  request.url = GURL("http://www.google.com/");
7400  request.load_flags = 0;
7401
7402  MockWrite data_writes1[] = {
7403    MockWrite("GET / HTTP/1.1\r\n"
7404              "Host: www.google.com\r\n"
7405              "Connection: keep-alive\r\n\r\n"),
7406  };
7407
7408  MockRead data_reads1[] = {
7409    MockRead("HTTP/1.1 401 Unauthorized\r\n"),
7410    MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
7411    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7412    MockRead("Content-Length: 14\r\n\r\n"),
7413    MockRead("Unauth"),
7414    MockRead(ASYNC, ERR_CONNECTION_RESET),
7415  };
7416
7417  StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
7418                                 data_writes1, arraysize(data_writes1));
7419  session_deps_.socket_factory->AddSocketDataProvider(&data1);
7420
7421  // After calling trans->RestartWithAuth(), this is the request we should
7422  // be issuing -- the final header line contains the credentials.
7423  MockWrite data_writes2[] = {
7424    MockWrite("GET / HTTP/1.1\r\n"
7425              "Host: www.google.com\r\n"
7426              "Connection: keep-alive\r\n"
7427              "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
7428  };
7429
7430  // Lastly, the server responds with the actual content.
7431  MockRead data_reads2[] = {
7432    MockRead("HTTP/1.1 200 OK\r\n"),
7433    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7434    MockRead("Content-Length: 100\r\n\r\n"),
7435    MockRead(SYNCHRONOUS, OK),
7436  };
7437
7438  StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
7439                                 data_writes2, arraysize(data_writes2));
7440  session_deps_.socket_factory->AddSocketDataProvider(&data2);
7441
7442  TestCompletionCallback callback1;
7443
7444  scoped_ptr<HttpTransaction> trans(
7445      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7446
7447  int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
7448  EXPECT_EQ(ERR_IO_PENDING, rv);
7449
7450  rv = callback1.WaitForResult();
7451  EXPECT_EQ(OK, rv);
7452
7453  const HttpResponseInfo* response = trans->GetResponseInfo();
7454  ASSERT_TRUE(response != NULL);
7455  EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
7456
7457  TestCompletionCallback callback2;
7458
7459  rv = trans->RestartWithAuth(
7460      AuthCredentials(kFoo, kBar), callback2.callback());
7461  EXPECT_EQ(ERR_IO_PENDING, rv);
7462
7463  rv = callback2.WaitForResult();
7464  EXPECT_EQ(OK, rv);
7465
7466  response = trans->GetResponseInfo();
7467  ASSERT_TRUE(response != NULL);
7468  EXPECT_TRUE(response->auth_challenge.get() == NULL);
7469  EXPECT_EQ(100, response->headers->GetContentLength());
7470}
7471
7472// Test HTTPS connections going through a proxy that sends extra data.
7473TEST_P(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
7474  session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
7475
7476  HttpRequestInfo request;
7477  request.method = "GET";
7478  request.url = GURL("https://www.google.com/");
7479  request.load_flags = 0;
7480
7481  MockRead proxy_reads[] = {
7482    MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
7483    MockRead(SYNCHRONOUS, OK)
7484  };
7485
7486  StaticSocketDataProvider data(proxy_reads, arraysize(proxy_reads), NULL, 0);
7487  SSLSocketDataProvider ssl(ASYNC, OK);
7488
7489  session_deps_.socket_factory->AddSocketDataProvider(&data);
7490  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7491
7492  TestCompletionCallback callback;
7493
7494  session_deps_.socket_factory->ResetNextMockIndexes();
7495
7496  scoped_ptr<HttpTransaction> trans(
7497      new HttpNetworkTransaction(DEFAULT_PRIORITY,
7498                                 CreateSession(&session_deps_)));
7499
7500  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7501  EXPECT_EQ(ERR_IO_PENDING, rv);
7502
7503  rv = callback.WaitForResult();
7504  EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
7505}
7506
7507TEST_P(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
7508  HttpRequestInfo request;
7509  request.method = "GET";
7510  request.url = GURL("http://www.google.com/");
7511  request.load_flags = 0;
7512
7513  scoped_ptr<HttpTransaction> trans(
7514      new HttpNetworkTransaction(DEFAULT_PRIORITY,
7515                                 CreateSession(&session_deps_)));
7516
7517  MockRead data_reads[] = {
7518    MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
7519    MockRead(SYNCHRONOUS, OK),
7520  };
7521
7522  StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
7523  session_deps_.socket_factory->AddSocketDataProvider(&data);
7524
7525  TestCompletionCallback callback;
7526
7527  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7528  EXPECT_EQ(ERR_IO_PENDING, rv);
7529
7530  EXPECT_EQ(OK, callback.WaitForResult());
7531
7532  const HttpResponseInfo* response = trans->GetResponseInfo();
7533  ASSERT_TRUE(response != NULL);
7534
7535  EXPECT_TRUE(response->headers.get() != NULL);
7536  EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
7537
7538  std::string response_data;
7539  rv = ReadTransaction(trans.get(), &response_data);
7540  EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH, rv);
7541}
7542
7543TEST_P(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
7544  base::FilePath temp_file_path;
7545  ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file_path));
7546  const uint64 kFakeSize = 100000;  // file is actually blank
7547  UploadFileElementReader::ScopedOverridingContentLengthForTests
7548      overriding_content_length(kFakeSize);
7549
7550  ScopedVector<UploadElementReader> element_readers;
7551  element_readers.push_back(
7552      new UploadFileElementReader(base::MessageLoopProxy::current().get(),
7553                                  temp_file_path,
7554                                  0,
7555                                  kuint64max,
7556                                  base::Time()));
7557  UploadDataStream upload_data_stream(&element_readers, 0);
7558
7559  HttpRequestInfo request;
7560  request.method = "POST";
7561  request.url = GURL("http://www.google.com/upload");
7562  request.upload_data_stream = &upload_data_stream;
7563  request.load_flags = 0;
7564
7565  scoped_ptr<HttpTransaction> trans(
7566      new HttpNetworkTransaction(DEFAULT_PRIORITY,
7567                                 CreateSession(&session_deps_)));
7568
7569  MockRead data_reads[] = {
7570    MockRead("HTTP/1.0 200 OK\r\n\r\n"),
7571    MockRead("hello world"),
7572    MockRead(SYNCHRONOUS, OK),
7573  };
7574  StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
7575  session_deps_.socket_factory->AddSocketDataProvider(&data);
7576
7577  TestCompletionCallback callback;
7578
7579  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7580  EXPECT_EQ(ERR_IO_PENDING, rv);
7581
7582  rv = callback.WaitForResult();
7583  EXPECT_EQ(OK, rv);
7584
7585  const HttpResponseInfo* response = trans->GetResponseInfo();
7586  ASSERT_TRUE(response != NULL);
7587
7588  EXPECT_TRUE(response->headers.get() != NULL);
7589  EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
7590
7591  std::string response_data;
7592  rv = ReadTransaction(trans.get(), &response_data);
7593  EXPECT_EQ(OK, rv);
7594  EXPECT_EQ("hello world", response_data);
7595
7596  base::DeleteFile(temp_file_path, false);
7597}
7598
7599TEST_P(HttpNetworkTransactionTest, UploadUnreadableFile) {
7600  base::FilePath temp_file;
7601  ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
7602  std::string temp_file_content("Unreadable file.");
7603  ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_content.c_str(),
7604                                   temp_file_content.length()));
7605  ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
7606
7607  ScopedVector<UploadElementReader> element_readers;
7608  element_readers.push_back(
7609      new UploadFileElementReader(base::MessageLoopProxy::current().get(),
7610                                  temp_file,
7611                                  0,
7612                                  kuint64max,
7613                                  base::Time()));
7614  UploadDataStream upload_data_stream(&element_readers, 0);
7615
7616  HttpRequestInfo request;
7617  request.method = "POST";
7618  request.url = GURL("http://www.google.com/upload");
7619  request.upload_data_stream = &upload_data_stream;
7620  request.load_flags = 0;
7621
7622  // If we try to upload an unreadable file, the network stack should report
7623  // the file size as zero and upload zero bytes for that file.
7624  scoped_ptr<HttpTransaction> trans(
7625      new HttpNetworkTransaction(DEFAULT_PRIORITY,
7626                                 CreateSession(&session_deps_)));
7627
7628  MockRead data_reads[] = {
7629    MockRead("HTTP/1.0 200 OK\r\n\r\n"),
7630    MockRead(SYNCHRONOUS, OK),
7631  };
7632  MockWrite data_writes[] = {
7633    MockWrite("POST /upload HTTP/1.1\r\n"
7634              "Host: www.google.com\r\n"
7635              "Connection: keep-alive\r\n"
7636              "Content-Length: 0\r\n\r\n"),
7637    MockWrite(SYNCHRONOUS, OK),
7638  };
7639  StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
7640                                arraysize(data_writes));
7641  session_deps_.socket_factory->AddSocketDataProvider(&data);
7642
7643  TestCompletionCallback callback;
7644
7645  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7646  EXPECT_EQ(ERR_IO_PENDING, rv);
7647
7648  rv = callback.WaitForResult();
7649  EXPECT_EQ(OK, rv);
7650
7651  const HttpResponseInfo* response = trans->GetResponseInfo();
7652  ASSERT_TRUE(response != NULL);
7653  EXPECT_TRUE(response->headers.get() != NULL);
7654  EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
7655
7656  base::DeleteFile(temp_file, false);
7657}
7658
7659TEST_P(HttpNetworkTransactionTest, UnreadableUploadFileAfterAuthRestart) {
7660  base::FilePath temp_file;
7661  ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
7662  std::string temp_file_contents("Unreadable file.");
7663  std::string unreadable_contents(temp_file_contents.length(), '\0');
7664  ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_contents.c_str(),
7665                                   temp_file_contents.length()));
7666
7667  ScopedVector<UploadElementReader> element_readers;
7668  element_readers.push_back(
7669      new UploadFileElementReader(base::MessageLoopProxy::current().get(),
7670                                  temp_file,
7671                                  0,
7672                                  kuint64max,
7673                                  base::Time()));
7674  UploadDataStream upload_data_stream(&element_readers, 0);
7675
7676  HttpRequestInfo request;
7677  request.method = "POST";
7678  request.url = GURL("http://www.google.com/upload");
7679  request.upload_data_stream = &upload_data_stream;
7680  request.load_flags = 0;
7681
7682  scoped_ptr<HttpTransaction> trans(
7683      new HttpNetworkTransaction(DEFAULT_PRIORITY,
7684                                 CreateSession(&session_deps_)));
7685
7686  MockRead data_reads[] = {
7687    MockRead("HTTP/1.1 401 Unauthorized\r\n"),
7688    MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
7689    MockRead("Content-Length: 0\r\n\r\n"),  // No response body.
7690
7691    MockRead("HTTP/1.1 200 OK\r\n"),
7692    MockRead("Content-Length: 0\r\n\r\n"),
7693    MockRead(SYNCHRONOUS, OK),
7694  };
7695  MockWrite data_writes[] = {
7696    MockWrite("POST /upload HTTP/1.1\r\n"
7697              "Host: www.google.com\r\n"
7698              "Connection: keep-alive\r\n"
7699              "Content-Length: 16\r\n\r\n"),
7700    MockWrite(SYNCHRONOUS, temp_file_contents.c_str()),
7701
7702    MockWrite("POST /upload HTTP/1.1\r\n"
7703              "Host: www.google.com\r\n"
7704              "Connection: keep-alive\r\n"
7705              "Content-Length: 0\r\n"
7706              "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
7707    MockWrite(SYNCHRONOUS, unreadable_contents.c_str(),
7708              temp_file_contents.length()),
7709    MockWrite(SYNCHRONOUS, OK),
7710  };
7711  StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
7712                                arraysize(data_writes));
7713  session_deps_.socket_factory->AddSocketDataProvider(&data);
7714
7715  TestCompletionCallback callback1;
7716
7717  int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
7718  EXPECT_EQ(ERR_IO_PENDING, rv);
7719
7720  rv = callback1.WaitForResult();
7721  EXPECT_EQ(OK, rv);
7722
7723  const HttpResponseInfo* response = trans->GetResponseInfo();
7724  ASSERT_TRUE(response != NULL);
7725  ASSERT_TRUE(response->headers.get() != NULL);
7726  EXPECT_EQ("HTTP/1.1 401 Unauthorized", response->headers->GetStatusLine());
7727  EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
7728
7729  // Now make the file unreadable and try again.
7730  ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
7731
7732  TestCompletionCallback callback2;
7733
7734  rv = trans->RestartWithAuth(
7735      AuthCredentials(kFoo, kBar), callback2.callback());
7736  EXPECT_EQ(ERR_IO_PENDING, rv);
7737
7738  rv = callback2.WaitForResult();
7739  EXPECT_EQ(OK, rv);
7740
7741  response = trans->GetResponseInfo();
7742  ASSERT_TRUE(response != NULL);
7743  EXPECT_TRUE(response->headers.get() != NULL);
7744  EXPECT_TRUE(response->auth_challenge.get() == NULL);
7745  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7746
7747  base::DeleteFile(temp_file, false);
7748}
7749
7750// Tests that changes to Auth realms are treated like auth rejections.
7751TEST_P(HttpNetworkTransactionTest, ChangeAuthRealms) {
7752
7753  HttpRequestInfo request;
7754  request.method = "GET";
7755  request.url = GURL("http://www.google.com/");
7756  request.load_flags = 0;
7757
7758  // First transaction will request a resource and receive a Basic challenge
7759  // with realm="first_realm".
7760  MockWrite data_writes1[] = {
7761    MockWrite("GET / HTTP/1.1\r\n"
7762              "Host: www.google.com\r\n"
7763              "Connection: keep-alive\r\n"
7764              "\r\n"),
7765  };
7766  MockRead data_reads1[] = {
7767    MockRead("HTTP/1.1 401 Unauthorized\r\n"
7768             "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
7769             "\r\n"),
7770  };
7771
7772  // After calling trans->RestartWithAuth(), provide an Authentication header
7773  // for first_realm. The server will reject and provide a challenge with
7774  // second_realm.
7775  MockWrite data_writes2[] = {
7776    MockWrite("GET / HTTP/1.1\r\n"
7777              "Host: www.google.com\r\n"
7778              "Connection: keep-alive\r\n"
7779              "Authorization: Basic Zmlyc3Q6YmF6\r\n"
7780              "\r\n"),
7781  };
7782  MockRead data_reads2[] = {
7783    MockRead("HTTP/1.1 401 Unauthorized\r\n"
7784             "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
7785             "\r\n"),
7786  };
7787
7788  // This again fails, and goes back to first_realm. Make sure that the
7789  // entry is removed from cache.
7790  MockWrite data_writes3[] = {
7791    MockWrite("GET / HTTP/1.1\r\n"
7792              "Host: www.google.com\r\n"
7793              "Connection: keep-alive\r\n"
7794              "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
7795              "\r\n"),
7796  };
7797  MockRead data_reads3[] = {
7798    MockRead("HTTP/1.1 401 Unauthorized\r\n"
7799             "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
7800             "\r\n"),
7801  };
7802
7803  // Try one last time (with the correct password) and get the resource.
7804  MockWrite data_writes4[] = {
7805    MockWrite("GET / HTTP/1.1\r\n"
7806              "Host: www.google.com\r\n"
7807              "Connection: keep-alive\r\n"
7808              "Authorization: Basic Zmlyc3Q6YmFy\r\n"
7809              "\r\n"),
7810  };
7811  MockRead data_reads4[] = {
7812    MockRead("HTTP/1.1 200 OK\r\n"
7813             "Content-Type: text/html; charset=iso-8859-1\r\n"
7814             "Content-Length: 5\r\n"
7815             "\r\n"
7816             "hello"),
7817  };
7818
7819  StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
7820                                 data_writes1, arraysize(data_writes1));
7821  StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
7822                                 data_writes2, arraysize(data_writes2));
7823  StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
7824                                 data_writes3, arraysize(data_writes3));
7825  StaticSocketDataProvider data4(data_reads4, arraysize(data_reads4),
7826                                 data_writes4, arraysize(data_writes4));
7827  session_deps_.socket_factory->AddSocketDataProvider(&data1);
7828  session_deps_.socket_factory->AddSocketDataProvider(&data2);
7829  session_deps_.socket_factory->AddSocketDataProvider(&data3);
7830  session_deps_.socket_factory->AddSocketDataProvider(&data4);
7831
7832  TestCompletionCallback callback1;
7833
7834  scoped_ptr<HttpTransaction> trans(
7835      new HttpNetworkTransaction(DEFAULT_PRIORITY,
7836                                 CreateSession(&session_deps_)));
7837
7838  // Issue the first request with Authorize headers. There should be a
7839  // password prompt for first_realm waiting to be filled in after the
7840  // transaction completes.
7841  int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
7842  EXPECT_EQ(ERR_IO_PENDING, rv);
7843  rv = callback1.WaitForResult();
7844  EXPECT_EQ(OK, rv);
7845  const HttpResponseInfo* response = trans->GetResponseInfo();
7846  ASSERT_TRUE(response != NULL);
7847  const AuthChallengeInfo* challenge = response->auth_challenge.get();
7848  ASSERT_FALSE(challenge == NULL);
7849  EXPECT_FALSE(challenge->is_proxy);
7850  EXPECT_EQ("www.google.com:80", challenge->challenger.ToString());
7851  EXPECT_EQ("first_realm", challenge->realm);
7852  EXPECT_EQ("basic", challenge->scheme);
7853
7854  // Issue the second request with an incorrect password. There should be a
7855  // password prompt for second_realm waiting to be filled in after the
7856  // transaction completes.
7857  TestCompletionCallback callback2;
7858  rv = trans->RestartWithAuth(
7859      AuthCredentials(kFirst, kBaz), callback2.callback());
7860  EXPECT_EQ(ERR_IO_PENDING, rv);
7861  rv = callback2.WaitForResult();
7862  EXPECT_EQ(OK, rv);
7863  response = trans->GetResponseInfo();
7864  ASSERT_TRUE(response != NULL);
7865  challenge = response->auth_challenge.get();
7866  ASSERT_FALSE(challenge == NULL);
7867  EXPECT_FALSE(challenge->is_proxy);
7868  EXPECT_EQ("www.google.com:80", challenge->challenger.ToString());
7869  EXPECT_EQ("second_realm", challenge->realm);
7870  EXPECT_EQ("basic", challenge->scheme);
7871
7872  // Issue the third request with another incorrect password. There should be
7873  // a password prompt for first_realm waiting to be filled in. If the password
7874  // prompt is not present, it indicates that the HttpAuthCacheEntry for
7875  // first_realm was not correctly removed.
7876  TestCompletionCallback callback3;
7877  rv = trans->RestartWithAuth(
7878      AuthCredentials(kSecond, kFou), callback3.callback());
7879  EXPECT_EQ(ERR_IO_PENDING, rv);
7880  rv = callback3.WaitForResult();
7881  EXPECT_EQ(OK, rv);
7882  response = trans->GetResponseInfo();
7883  ASSERT_TRUE(response != NULL);
7884  challenge = response->auth_challenge.get();
7885  ASSERT_FALSE(challenge == NULL);
7886  EXPECT_FALSE(challenge->is_proxy);
7887  EXPECT_EQ("www.google.com:80", challenge->challenger.ToString());
7888  EXPECT_EQ("first_realm", challenge->realm);
7889  EXPECT_EQ("basic", challenge->scheme);
7890
7891  // Issue the fourth request with the correct password and username.
7892  TestCompletionCallback callback4;
7893  rv = trans->RestartWithAuth(
7894      AuthCredentials(kFirst, kBar), callback4.callback());
7895  EXPECT_EQ(ERR_IO_PENDING, rv);
7896  rv = callback4.WaitForResult();
7897  EXPECT_EQ(OK, rv);
7898  response = trans->GetResponseInfo();
7899  ASSERT_TRUE(response != NULL);
7900  EXPECT_TRUE(response->auth_challenge.get() == NULL);
7901}
7902
7903TEST_P(HttpNetworkTransactionTest, HonorAlternateProtocolHeader) {
7904  HttpStreamFactory::SetNextProtos(SpdyNextProtos());
7905  HttpStreamFactory::set_use_alternate_protocols(true);
7906
7907  std::string alternate_protocol_http_header =
7908      GetAlternateProtocolHttpHeader();
7909
7910  MockRead data_reads[] = {
7911    MockRead("HTTP/1.1 200 OK\r\n"),
7912    MockRead(alternate_protocol_http_header.c_str()),
7913    MockRead("hello world"),
7914    MockRead(SYNCHRONOUS, OK),
7915  };
7916
7917  HttpRequestInfo request;
7918  request.method = "GET";
7919  request.url = GURL("http://www.google.com/");
7920  request.load_flags = 0;
7921
7922  StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
7923
7924  session_deps_.socket_factory->AddSocketDataProvider(&data);
7925
7926  TestCompletionCallback callback;
7927
7928  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7929  scoped_ptr<HttpTransaction> trans(
7930      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7931
7932  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7933  EXPECT_EQ(ERR_IO_PENDING, rv);
7934
7935  HostPortPair http_host_port_pair("www.google.com", 80);
7936  const HttpServerProperties& http_server_properties =
7937      *session->http_server_properties();
7938  EXPECT_FALSE(
7939      http_server_properties.HasAlternateProtocol(http_host_port_pair));
7940
7941  EXPECT_EQ(OK, callback.WaitForResult());
7942
7943  const HttpResponseInfo* response = trans->GetResponseInfo();
7944  ASSERT_TRUE(response != NULL);
7945  ASSERT_TRUE(response->headers.get() != NULL);
7946  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7947  EXPECT_FALSE(response->was_fetched_via_spdy);
7948  EXPECT_FALSE(response->was_npn_negotiated);
7949
7950  std::string response_data;
7951  ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7952  EXPECT_EQ("hello world", response_data);
7953
7954  ASSERT_TRUE(http_server_properties.HasAlternateProtocol(http_host_port_pair));
7955  const PortAlternateProtocolPair alternate =
7956      http_server_properties.GetAlternateProtocol(http_host_port_pair);
7957  PortAlternateProtocolPair expected_alternate;
7958  expected_alternate.port = 443;
7959  expected_alternate.protocol = AlternateProtocolFromNextProto(GetParam());
7960  EXPECT_TRUE(expected_alternate.Equals(alternate));
7961}
7962
7963TEST_P(HttpNetworkTransactionTest,
7964       MarkBrokenAlternateProtocolAndFallback) {
7965  HttpStreamFactory::set_use_alternate_protocols(true);
7966
7967  HttpRequestInfo request;
7968  request.method = "GET";
7969  request.url = GURL("http://www.google.com/");
7970  request.load_flags = 0;
7971
7972  MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
7973  StaticSocketDataProvider first_data;
7974  first_data.set_connect_data(mock_connect);
7975  session_deps_.socket_factory->AddSocketDataProvider(&first_data);
7976
7977  MockRead data_reads[] = {
7978    MockRead("HTTP/1.1 200 OK\r\n\r\n"),
7979    MockRead("hello world"),
7980    MockRead(ASYNC, OK),
7981  };
7982  StaticSocketDataProvider second_data(
7983      data_reads, arraysize(data_reads), NULL, 0);
7984  session_deps_.socket_factory->AddSocketDataProvider(&second_data);
7985
7986  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7987
7988  base::WeakPtr<HttpServerProperties> http_server_properties =
7989      session->http_server_properties();
7990  // Port must be < 1024, or the header will be ignored (since initial port was
7991  // port 80 (another restricted port).
7992  http_server_properties->SetAlternateProtocol(
7993      HostPortPair::FromURL(request.url),
7994      666 /* port is ignored by MockConnect anyway */,
7995      AlternateProtocolFromNextProto(GetParam()));
7996
7997  scoped_ptr<HttpTransaction> trans(
7998      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7999  TestCompletionCallback callback;
8000
8001  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8002  EXPECT_EQ(ERR_IO_PENDING, rv);
8003  EXPECT_EQ(OK, callback.WaitForResult());
8004
8005  const HttpResponseInfo* response = trans->GetResponseInfo();
8006  ASSERT_TRUE(response != NULL);
8007  ASSERT_TRUE(response->headers.get() != NULL);
8008  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8009
8010  std::string response_data;
8011  ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8012  EXPECT_EQ("hello world", response_data);
8013
8014  ASSERT_TRUE(http_server_properties->HasAlternateProtocol(
8015      HostPortPair::FromURL(request.url)));
8016  const PortAlternateProtocolPair alternate =
8017      http_server_properties->GetAlternateProtocol(
8018          HostPortPair::FromURL(request.url));
8019  EXPECT_EQ(ALTERNATE_PROTOCOL_BROKEN, alternate.protocol);
8020}
8021
8022TEST_P(HttpNetworkTransactionTest,
8023       AlternateProtocolPortRestrictedBlocked) {
8024  // Ensure that we're not allowed to redirect traffic via an alternate
8025  // protocol to an unrestricted (port >= 1024) when the original traffic was
8026  // on a restricted port (port < 1024).  Ensure that we can redirect in all
8027  // other cases.
8028  HttpStreamFactory::set_use_alternate_protocols(true);
8029
8030  HttpRequestInfo restricted_port_request;
8031  restricted_port_request.method = "GET";
8032  restricted_port_request.url = GURL("http://www.google.com:1023/");
8033  restricted_port_request.load_flags = 0;
8034
8035  MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
8036  StaticSocketDataProvider first_data;
8037  first_data.set_connect_data(mock_connect);
8038  session_deps_.socket_factory->AddSocketDataProvider(&first_data);
8039
8040  MockRead data_reads[] = {
8041    MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8042    MockRead("hello world"),
8043    MockRead(ASYNC, OK),
8044  };
8045  StaticSocketDataProvider second_data(
8046      data_reads, arraysize(data_reads), NULL, 0);
8047  session_deps_.socket_factory->AddSocketDataProvider(&second_data);
8048
8049  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8050
8051  base::WeakPtr<HttpServerProperties> http_server_properties =
8052      session->http_server_properties();
8053  const int kUnrestrictedAlternatePort = 1024;
8054  http_server_properties->SetAlternateProtocol(
8055      HostPortPair::FromURL(restricted_port_request.url),
8056      kUnrestrictedAlternatePort,
8057      AlternateProtocolFromNextProto(GetParam()));
8058
8059  scoped_ptr<HttpTransaction> trans(
8060      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8061  TestCompletionCallback callback;
8062
8063  int rv = trans->Start(
8064      &restricted_port_request,
8065      callback.callback(), BoundNetLog());
8066  EXPECT_EQ(ERR_IO_PENDING, rv);
8067  // Invalid change to unrestricted port should fail.
8068  EXPECT_EQ(ERR_CONNECTION_REFUSED, callback.WaitForResult());
8069}
8070
8071TEST_P(HttpNetworkTransactionTest,
8072       AlternateProtocolPortRestrictedPermitted) {
8073  // Ensure that we're allowed to redirect traffic via an alternate
8074  // protocol to an unrestricted (port >= 1024) when the original traffic was
8075  // on a restricted port (port < 1024) if we set
8076  // enable_user_alternate_protocol_ports.
8077
8078  HttpStreamFactory::set_use_alternate_protocols(true);
8079  session_deps_.enable_user_alternate_protocol_ports = true;
8080
8081  HttpRequestInfo restricted_port_request;
8082  restricted_port_request.method = "GET";
8083  restricted_port_request.url = GURL("http://www.google.com:1023/");
8084  restricted_port_request.load_flags = 0;
8085
8086  MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
8087  StaticSocketDataProvider first_data;
8088  first_data.set_connect_data(mock_connect);
8089  session_deps_.socket_factory->AddSocketDataProvider(&first_data);
8090
8091  MockRead data_reads[] = {
8092    MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8093    MockRead("hello world"),
8094    MockRead(ASYNC, OK),
8095  };
8096  StaticSocketDataProvider second_data(
8097      data_reads, arraysize(data_reads), NULL, 0);
8098  session_deps_.socket_factory->AddSocketDataProvider(&second_data);
8099
8100  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8101
8102  base::WeakPtr<HttpServerProperties> http_server_properties =
8103      session->http_server_properties();
8104  const int kUnrestrictedAlternatePort = 1024;
8105  http_server_properties->SetAlternateProtocol(
8106      HostPortPair::FromURL(restricted_port_request.url),
8107      kUnrestrictedAlternatePort,
8108      AlternateProtocolFromNextProto(GetParam()));
8109
8110  scoped_ptr<HttpTransaction> trans(
8111      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8112  TestCompletionCallback callback;
8113
8114  EXPECT_EQ(ERR_IO_PENDING, trans->Start(
8115      &restricted_port_request,
8116      callback.callback(), BoundNetLog()));
8117  // Change to unrestricted port should succeed.
8118  EXPECT_EQ(OK, callback.WaitForResult());
8119}
8120
8121TEST_P(HttpNetworkTransactionTest,
8122       AlternateProtocolPortRestrictedAllowed) {
8123  // Ensure that we're not allowed to redirect traffic via an alternate
8124  // protocol to an unrestricted (port >= 1024) when the original traffic was
8125  // on a restricted port (port < 1024).  Ensure that we can redirect in all
8126  // other cases.
8127  HttpStreamFactory::set_use_alternate_protocols(true);
8128
8129  HttpRequestInfo restricted_port_request;
8130  restricted_port_request.method = "GET";
8131  restricted_port_request.url = GURL("http://www.google.com:1023/");
8132  restricted_port_request.load_flags = 0;
8133
8134  MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
8135  StaticSocketDataProvider first_data;
8136  first_data.set_connect_data(mock_connect);
8137  session_deps_.socket_factory->AddSocketDataProvider(&first_data);
8138
8139  MockRead data_reads[] = {
8140    MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8141    MockRead("hello world"),
8142    MockRead(ASYNC, OK),
8143  };
8144  StaticSocketDataProvider second_data(
8145      data_reads, arraysize(data_reads), NULL, 0);
8146  session_deps_.socket_factory->AddSocketDataProvider(&second_data);
8147
8148  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8149
8150  base::WeakPtr<HttpServerProperties> http_server_properties =
8151      session->http_server_properties();
8152  const int kRestrictedAlternatePort = 80;
8153  http_server_properties->SetAlternateProtocol(
8154      HostPortPair::FromURL(restricted_port_request.url),
8155      kRestrictedAlternatePort,
8156      AlternateProtocolFromNextProto(GetParam()));
8157
8158  scoped_ptr<HttpTransaction> trans(
8159      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8160  TestCompletionCallback callback;
8161
8162  int rv = trans->Start(
8163      &restricted_port_request,
8164      callback.callback(), BoundNetLog());
8165  EXPECT_EQ(ERR_IO_PENDING, rv);
8166  // Valid change to restricted port should pass.
8167  EXPECT_EQ(OK, callback.WaitForResult());
8168}
8169
8170TEST_P(HttpNetworkTransactionTest,
8171       AlternateProtocolPortUnrestrictedAllowed1) {
8172  // Ensure that we're not allowed to redirect traffic via an alternate
8173  // protocol to an unrestricted (port >= 1024) when the original traffic was
8174  // on a restricted port (port < 1024).  Ensure that we can redirect in all
8175  // other cases.
8176  HttpStreamFactory::set_use_alternate_protocols(true);
8177
8178  HttpRequestInfo unrestricted_port_request;
8179  unrestricted_port_request.method = "GET";
8180  unrestricted_port_request.url = GURL("http://www.google.com:1024/");
8181  unrestricted_port_request.load_flags = 0;
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  const int kRestrictedAlternatePort = 80;
8202  http_server_properties->SetAlternateProtocol(
8203      HostPortPair::FromURL(unrestricted_port_request.url),
8204      kRestrictedAlternatePort,
8205      AlternateProtocolFromNextProto(GetParam()));
8206
8207  scoped_ptr<HttpTransaction> trans(
8208      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8209  TestCompletionCallback callback;
8210
8211  int rv = trans->Start(
8212      &unrestricted_port_request, callback.callback(), BoundNetLog());
8213  EXPECT_EQ(ERR_IO_PENDING, rv);
8214  // Valid change to restricted port should pass.
8215  EXPECT_EQ(OK, callback.WaitForResult());
8216}
8217
8218TEST_P(HttpNetworkTransactionTest,
8219       AlternateProtocolPortUnrestrictedAllowed2) {
8220  // Ensure that we're not allowed to redirect traffic via an alternate
8221  // protocol to an unrestricted (port >= 1024) when the original traffic was
8222  // on a restricted port (port < 1024).  Ensure that we can redirect in all
8223  // other cases.
8224  HttpStreamFactory::set_use_alternate_protocols(true);
8225
8226  HttpRequestInfo unrestricted_port_request;
8227  unrestricted_port_request.method = "GET";
8228  unrestricted_port_request.url = GURL("http://www.google.com:1024/");
8229  unrestricted_port_request.load_flags = 0;
8230
8231  MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
8232  StaticSocketDataProvider first_data;
8233  first_data.set_connect_data(mock_connect);
8234  session_deps_.socket_factory->AddSocketDataProvider(&first_data);
8235
8236  MockRead data_reads[] = {
8237    MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8238    MockRead("hello world"),
8239    MockRead(ASYNC, OK),
8240  };
8241  StaticSocketDataProvider second_data(
8242      data_reads, arraysize(data_reads), NULL, 0);
8243  session_deps_.socket_factory->AddSocketDataProvider(&second_data);
8244
8245  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8246
8247  base::WeakPtr<HttpServerProperties> http_server_properties =
8248      session->http_server_properties();
8249  const int kUnrestrictedAlternatePort = 1024;
8250  http_server_properties->SetAlternateProtocol(
8251      HostPortPair::FromURL(unrestricted_port_request.url),
8252      kUnrestrictedAlternatePort,
8253      AlternateProtocolFromNextProto(GetParam()));
8254
8255  scoped_ptr<HttpTransaction> trans(
8256      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8257  TestCompletionCallback callback;
8258
8259  int rv = trans->Start(
8260      &unrestricted_port_request, callback.callback(), BoundNetLog());
8261  EXPECT_EQ(ERR_IO_PENDING, rv);
8262  // Valid change to an unrestricted port should pass.
8263  EXPECT_EQ(OK, callback.WaitForResult());
8264}
8265
8266TEST_P(HttpNetworkTransactionTest,
8267       AlternateProtocolUnsafeBlocked) {
8268  // Ensure that we're not allowed to redirect traffic via an alternate
8269  // protocol to an unsafe port, and that we resume the second
8270  // HttpStreamFactoryImpl::Job once the alternate protocol request fails.
8271  HttpStreamFactory::set_use_alternate_protocols(true);
8272
8273  HttpRequestInfo request;
8274  request.method = "GET";
8275  request.url = GURL("http://www.google.com/");
8276  request.load_flags = 0;
8277
8278  // The alternate protocol request will error out before we attempt to connect,
8279  // so only the standard HTTP request will try to connect.
8280  MockRead data_reads[] = {
8281    MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8282    MockRead("hello world"),
8283    MockRead(ASYNC, OK),
8284  };
8285  StaticSocketDataProvider data(
8286      data_reads, arraysize(data_reads), NULL, 0);
8287  session_deps_.socket_factory->AddSocketDataProvider(&data);
8288
8289  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8290
8291  base::WeakPtr<HttpServerProperties> http_server_properties =
8292      session->http_server_properties();
8293  const int kUnsafePort = 7;
8294  http_server_properties->SetAlternateProtocol(
8295      HostPortPair::FromURL(request.url),
8296      kUnsafePort,
8297      AlternateProtocolFromNextProto(GetParam()));
8298
8299  scoped_ptr<HttpTransaction> trans(
8300      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8301  TestCompletionCallback callback;
8302
8303  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8304  EXPECT_EQ(ERR_IO_PENDING, rv);
8305  // The HTTP request should succeed.
8306  EXPECT_EQ(OK, callback.WaitForResult());
8307
8308  // Disable alternate protocol before the asserts.
8309  HttpStreamFactory::set_use_alternate_protocols(false);
8310
8311  const HttpResponseInfo* response = trans->GetResponseInfo();
8312  ASSERT_TRUE(response != NULL);
8313  ASSERT_TRUE(response->headers.get() != NULL);
8314  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8315
8316  std::string response_data;
8317  ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8318  EXPECT_EQ("hello world", response_data);
8319}
8320
8321TEST_P(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) {
8322  HttpStreamFactory::set_use_alternate_protocols(true);
8323  HttpStreamFactory::SetNextProtos(SpdyNextProtos());
8324
8325  HttpRequestInfo request;
8326  request.method = "GET";
8327  request.url = GURL("http://www.google.com/");
8328  request.load_flags = 0;
8329
8330  std::string alternate_protocol_http_header =
8331      GetAlternateProtocolHttpHeader();
8332
8333  MockRead data_reads[] = {
8334    MockRead("HTTP/1.1 200 OK\r\n"),
8335    MockRead(alternate_protocol_http_header.c_str()),
8336    MockRead("hello world"),
8337    MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
8338    MockRead(ASYNC, OK)
8339  };
8340
8341  StaticSocketDataProvider first_transaction(
8342      data_reads, arraysize(data_reads), NULL, 0);
8343  session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
8344
8345  SSLSocketDataProvider ssl(ASYNC, OK);
8346  ssl.SetNextProto(GetParam());
8347  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
8348
8349  scoped_ptr<SpdyFrame> req(
8350      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
8351  MockWrite spdy_writes[] = { CreateMockWrite(*req) };
8352
8353  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
8354  scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
8355  MockRead spdy_reads[] = {
8356    CreateMockRead(*resp),
8357    CreateMockRead(*data),
8358    MockRead(ASYNC, 0, 0),
8359  };
8360
8361  DelayedSocketData spdy_data(
8362      1,  // wait for one write to finish before reading.
8363      spdy_reads, arraysize(spdy_reads),
8364      spdy_writes, arraysize(spdy_writes));
8365  session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
8366
8367  MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
8368  StaticSocketDataProvider hanging_non_alternate_protocol_socket(
8369      NULL, 0, NULL, 0);
8370  hanging_non_alternate_protocol_socket.set_connect_data(
8371      never_finishing_connect);
8372  session_deps_.socket_factory->AddSocketDataProvider(
8373      &hanging_non_alternate_protocol_socket);
8374
8375  TestCompletionCallback callback;
8376
8377  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8378  scoped_ptr<HttpTransaction> trans(
8379      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8380
8381  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8382  EXPECT_EQ(ERR_IO_PENDING, rv);
8383  EXPECT_EQ(OK, callback.WaitForResult());
8384
8385  const HttpResponseInfo* response = trans->GetResponseInfo();
8386  ASSERT_TRUE(response != NULL);
8387  ASSERT_TRUE(response->headers.get() != NULL);
8388  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8389
8390  std::string response_data;
8391  ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8392  EXPECT_EQ("hello world", response_data);
8393
8394  trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8395
8396  rv = trans->Start(&request, callback.callback(), BoundNetLog());
8397  EXPECT_EQ(ERR_IO_PENDING, rv);
8398  EXPECT_EQ(OK, callback.WaitForResult());
8399
8400  response = trans->GetResponseInfo();
8401  ASSERT_TRUE(response != NULL);
8402  ASSERT_TRUE(response->headers.get() != NULL);
8403  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8404  EXPECT_TRUE(response->was_fetched_via_spdy);
8405  EXPECT_TRUE(response->was_npn_negotiated);
8406
8407  ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8408  EXPECT_EQ("hello!", response_data);
8409}
8410
8411TEST_P(HttpNetworkTransactionTest, AlternateProtocolWithSpdyLateBinding) {
8412  HttpStreamFactory::set_use_alternate_protocols(true);
8413  HttpStreamFactory::SetNextProtos(SpdyNextProtos());
8414
8415  HttpRequestInfo request;
8416  request.method = "GET";
8417  request.url = GURL("http://www.google.com/");
8418  request.load_flags = 0;
8419
8420  std::string alternate_protocol_http_header =
8421      GetAlternateProtocolHttpHeader();
8422
8423  MockRead data_reads[] = {
8424    MockRead("HTTP/1.1 200 OK\r\n"),
8425    MockRead(alternate_protocol_http_header.c_str()),
8426    MockRead("hello world"),
8427    MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
8428    MockRead(ASYNC, OK),
8429  };
8430
8431  StaticSocketDataProvider first_transaction(
8432      data_reads, arraysize(data_reads), NULL, 0);
8433  // Socket 1 is the HTTP transaction with the Alternate-Protocol header.
8434  session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
8435
8436  MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
8437  StaticSocketDataProvider hanging_socket(
8438      NULL, 0, NULL, 0);
8439  hanging_socket.set_connect_data(never_finishing_connect);
8440  // Socket 2 and 3 are the hanging Alternate-Protocol and
8441  // non-Alternate-Protocol jobs from the 2nd transaction.
8442  session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket);
8443  session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket);
8444
8445  SSLSocketDataProvider ssl(ASYNC, OK);
8446  ssl.SetNextProto(GetParam());
8447  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
8448
8449  scoped_ptr<SpdyFrame> req1(
8450      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
8451  scoped_ptr<SpdyFrame> req2(
8452      spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
8453  MockWrite spdy_writes[] = {
8454    CreateMockWrite(*req1),
8455    CreateMockWrite(*req2),
8456  };
8457  scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
8458  scoped_ptr<SpdyFrame> data1(spdy_util_.ConstructSpdyBodyFrame(1, true));
8459  scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
8460  scoped_ptr<SpdyFrame> data2(spdy_util_.ConstructSpdyBodyFrame(3, true));
8461  MockRead spdy_reads[] = {
8462    CreateMockRead(*resp1),
8463    CreateMockRead(*data1),
8464    CreateMockRead(*resp2),
8465    CreateMockRead(*data2),
8466    MockRead(ASYNC, 0, 0),
8467  };
8468
8469  DelayedSocketData spdy_data(
8470      2,  // wait for writes to finish before reading.
8471      spdy_reads, arraysize(spdy_reads),
8472      spdy_writes, arraysize(spdy_writes));
8473  // Socket 4 is the successful Alternate-Protocol for transaction 3.
8474  session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
8475
8476  // Socket 5 is the unsuccessful non-Alternate-Protocol for transaction 3.
8477  session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket);
8478
8479  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8480  TestCompletionCallback callback1;
8481  HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
8482
8483  int rv = trans1.Start(&request, callback1.callback(), BoundNetLog());
8484  EXPECT_EQ(ERR_IO_PENDING, rv);
8485  EXPECT_EQ(OK, callback1.WaitForResult());
8486
8487  const HttpResponseInfo* response = trans1.GetResponseInfo();
8488  ASSERT_TRUE(response != NULL);
8489  ASSERT_TRUE(response->headers.get() != NULL);
8490  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8491
8492  std::string response_data;
8493  ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
8494  EXPECT_EQ("hello world", response_data);
8495
8496  TestCompletionCallback callback2;
8497  HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
8498  rv = trans2.Start(&request, callback2.callback(), BoundNetLog());
8499  EXPECT_EQ(ERR_IO_PENDING, rv);
8500
8501  TestCompletionCallback callback3;
8502  HttpNetworkTransaction trans3(DEFAULT_PRIORITY, session.get());
8503  rv = trans3.Start(&request, callback3.callback(), BoundNetLog());
8504  EXPECT_EQ(ERR_IO_PENDING, rv);
8505
8506  EXPECT_EQ(OK, callback2.WaitForResult());
8507  EXPECT_EQ(OK, callback3.WaitForResult());
8508
8509  response = trans2.GetResponseInfo();
8510  ASSERT_TRUE(response != NULL);
8511  ASSERT_TRUE(response->headers.get() != NULL);
8512  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8513  EXPECT_TRUE(response->was_fetched_via_spdy);
8514  EXPECT_TRUE(response->was_npn_negotiated);
8515  ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
8516  EXPECT_EQ("hello!", response_data);
8517
8518  response = trans3.GetResponseInfo();
8519  ASSERT_TRUE(response != NULL);
8520  ASSERT_TRUE(response->headers.get() != NULL);
8521  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8522  EXPECT_TRUE(response->was_fetched_via_spdy);
8523  EXPECT_TRUE(response->was_npn_negotiated);
8524  ASSERT_EQ(OK, ReadTransaction(&trans3, &response_data));
8525  EXPECT_EQ("hello!", response_data);
8526}
8527
8528TEST_P(HttpNetworkTransactionTest, StallAlternateProtocolForNpnSpdy) {
8529  HttpStreamFactory::set_use_alternate_protocols(true);
8530  HttpStreamFactory::SetNextProtos(SpdyNextProtos());
8531
8532  HttpRequestInfo request;
8533  request.method = "GET";
8534  request.url = GURL("http://www.google.com/");
8535  request.load_flags = 0;
8536
8537  std::string alternate_protocol_http_header =
8538      GetAlternateProtocolHttpHeader();
8539
8540  MockRead data_reads[] = {
8541    MockRead("HTTP/1.1 200 OK\r\n"),
8542    MockRead(alternate_protocol_http_header.c_str()),
8543    MockRead("hello world"),
8544    MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
8545    MockRead(ASYNC, OK),
8546  };
8547
8548  StaticSocketDataProvider first_transaction(
8549      data_reads, arraysize(data_reads), NULL, 0);
8550  session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
8551
8552  SSLSocketDataProvider ssl(ASYNC, OK);
8553  ssl.SetNextProto(GetParam());
8554  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
8555
8556  MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
8557  StaticSocketDataProvider hanging_alternate_protocol_socket(
8558      NULL, 0, NULL, 0);
8559  hanging_alternate_protocol_socket.set_connect_data(
8560      never_finishing_connect);
8561  session_deps_.socket_factory->AddSocketDataProvider(
8562      &hanging_alternate_protocol_socket);
8563
8564  // 2nd request is just a copy of the first one, over HTTP again.
8565  session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
8566
8567  TestCompletionCallback callback;
8568
8569  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8570  scoped_ptr<HttpTransaction> trans(
8571      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8572
8573  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8574  EXPECT_EQ(ERR_IO_PENDING, rv);
8575  EXPECT_EQ(OK, callback.WaitForResult());
8576
8577  const HttpResponseInfo* response = trans->GetResponseInfo();
8578  ASSERT_TRUE(response != NULL);
8579  ASSERT_TRUE(response->headers.get() != NULL);
8580  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8581
8582  std::string response_data;
8583  ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8584  EXPECT_EQ("hello world", response_data);
8585
8586  trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8587
8588  rv = trans->Start(&request, callback.callback(), BoundNetLog());
8589  EXPECT_EQ(ERR_IO_PENDING, rv);
8590  EXPECT_EQ(OK, callback.WaitForResult());
8591
8592  response = trans->GetResponseInfo();
8593  ASSERT_TRUE(response != NULL);
8594  ASSERT_TRUE(response->headers.get() != NULL);
8595  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8596  EXPECT_FALSE(response->was_fetched_via_spdy);
8597  EXPECT_FALSE(response->was_npn_negotiated);
8598
8599  ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8600  EXPECT_EQ("hello world", response_data);
8601}
8602
8603class CapturingProxyResolver : public ProxyResolver {
8604 public:
8605  CapturingProxyResolver() : ProxyResolver(false /* expects_pac_bytes */) {}
8606  virtual ~CapturingProxyResolver() {}
8607
8608  virtual int GetProxyForURL(const GURL& url,
8609                             ProxyInfo* results,
8610                             const CompletionCallback& callback,
8611                             RequestHandle* request,
8612                             const BoundNetLog& net_log) OVERRIDE {
8613    ProxyServer proxy_server(ProxyServer::SCHEME_HTTP,
8614                             HostPortPair("myproxy", 80));
8615    results->UseProxyServer(proxy_server);
8616    resolved_.push_back(url);
8617    return OK;
8618  }
8619
8620  virtual void CancelRequest(RequestHandle request) OVERRIDE {
8621    NOTREACHED();
8622  }
8623
8624  virtual LoadState GetLoadState(RequestHandle request) const OVERRIDE {
8625    NOTREACHED();
8626    return LOAD_STATE_IDLE;
8627  }
8628
8629  virtual void CancelSetPacScript() OVERRIDE {
8630    NOTREACHED();
8631  }
8632
8633  virtual int SetPacScript(const scoped_refptr<ProxyResolverScriptData>&,
8634                           const CompletionCallback& /*callback*/) OVERRIDE {
8635    return OK;
8636  }
8637
8638  const std::vector<GURL>& resolved() const { return resolved_; }
8639
8640 private:
8641  std::vector<GURL> resolved_;
8642
8643  DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver);
8644};
8645
8646TEST_P(HttpNetworkTransactionTest,
8647       UseAlternateProtocolForTunneledNpnSpdy) {
8648  HttpStreamFactory::set_use_alternate_protocols(true);
8649  HttpStreamFactory::SetNextProtos(SpdyNextProtos());
8650
8651  ProxyConfig proxy_config;
8652  proxy_config.set_auto_detect(true);
8653  proxy_config.set_pac_url(GURL("http://fooproxyurl"));
8654
8655  CapturingProxyResolver* capturing_proxy_resolver =
8656      new CapturingProxyResolver();
8657  session_deps_.proxy_service.reset(new ProxyService(
8658      new ProxyConfigServiceFixed(proxy_config), capturing_proxy_resolver,
8659      NULL));
8660  CapturingNetLog net_log;
8661  session_deps_.net_log = &net_log;
8662
8663  HttpRequestInfo request;
8664  request.method = "GET";
8665  request.url = GURL("http://www.google.com/");
8666  request.load_flags = 0;
8667
8668  std::string alternate_protocol_http_header =
8669      GetAlternateProtocolHttpHeader();
8670
8671  MockRead data_reads[] = {
8672    MockRead("HTTP/1.1 200 OK\r\n"),
8673    MockRead(alternate_protocol_http_header.c_str()),
8674    MockRead("hello world"),
8675    MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
8676    MockRead(ASYNC, OK),
8677  };
8678
8679  StaticSocketDataProvider first_transaction(
8680      data_reads, arraysize(data_reads), NULL, 0);
8681  session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
8682
8683  SSLSocketDataProvider ssl(ASYNC, OK);
8684  ssl.SetNextProto(GetParam());
8685  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
8686
8687  scoped_ptr<SpdyFrame> req(
8688      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
8689  MockWrite spdy_writes[] = {
8690    MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
8691              "Host: www.google.com\r\n"
8692              "Proxy-Connection: keep-alive\r\n\r\n"),  // 0
8693    CreateMockWrite(*req),                              // 3
8694  };
8695
8696  const char kCONNECTResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
8697
8698  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
8699  scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
8700  MockRead spdy_reads[] = {
8701    MockRead(ASYNC, kCONNECTResponse, arraysize(kCONNECTResponse) - 1, 1),  // 1
8702    CreateMockRead(*resp.get(), 4),  // 2, 4
8703    CreateMockRead(*data.get(), 4),  // 5
8704    MockRead(ASYNC, 0, 0, 4),  // 6
8705  };
8706
8707  OrderedSocketData spdy_data(
8708      spdy_reads, arraysize(spdy_reads),
8709      spdy_writes, arraysize(spdy_writes));
8710  session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
8711
8712  MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
8713  StaticSocketDataProvider hanging_non_alternate_protocol_socket(
8714      NULL, 0, NULL, 0);
8715  hanging_non_alternate_protocol_socket.set_connect_data(
8716      never_finishing_connect);
8717  session_deps_.socket_factory->AddSocketDataProvider(
8718      &hanging_non_alternate_protocol_socket);
8719
8720  TestCompletionCallback callback;
8721
8722  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8723  scoped_ptr<HttpTransaction> trans(
8724      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8725
8726  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8727  EXPECT_EQ(ERR_IO_PENDING, rv);
8728  EXPECT_EQ(OK, callback.WaitForResult());
8729
8730  const HttpResponseInfo* response = trans->GetResponseInfo();
8731  ASSERT_TRUE(response != NULL);
8732  ASSERT_TRUE(response->headers.get() != NULL);
8733  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8734  EXPECT_FALSE(response->was_fetched_via_spdy);
8735  EXPECT_FALSE(response->was_npn_negotiated);
8736
8737  std::string response_data;
8738  ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8739  EXPECT_EQ("hello world", response_data);
8740
8741  trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8742
8743  rv = trans->Start(&request, callback.callback(), BoundNetLog());
8744  EXPECT_EQ(ERR_IO_PENDING, rv);
8745  EXPECT_EQ(OK, callback.WaitForResult());
8746
8747  response = trans->GetResponseInfo();
8748  ASSERT_TRUE(response != NULL);
8749  ASSERT_TRUE(response->headers.get() != NULL);
8750  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8751  EXPECT_TRUE(response->was_fetched_via_spdy);
8752  EXPECT_TRUE(response->was_npn_negotiated);
8753
8754  ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8755  EXPECT_EQ("hello!", response_data);
8756  ASSERT_EQ(3u, capturing_proxy_resolver->resolved().size());
8757  EXPECT_EQ("http://www.google.com/",
8758            capturing_proxy_resolver->resolved()[0].spec());
8759  EXPECT_EQ("https://www.google.com/",
8760            capturing_proxy_resolver->resolved()[1].spec());
8761
8762  LoadTimingInfo load_timing_info;
8763  EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
8764  TestLoadTimingNotReusedWithPac(load_timing_info,
8765                                 CONNECT_TIMING_HAS_SSL_TIMES);
8766}
8767
8768TEST_P(HttpNetworkTransactionTest,
8769       UseAlternateProtocolForNpnSpdyWithExistingSpdySession) {
8770  HttpStreamFactory::set_use_alternate_protocols(true);
8771  HttpStreamFactory::SetNextProtos(SpdyNextProtos());
8772
8773  HttpRequestInfo request;
8774  request.method = "GET";
8775  request.url = GURL("http://www.google.com/");
8776  request.load_flags = 0;
8777
8778  std::string alternate_protocol_http_header =
8779      GetAlternateProtocolHttpHeader();
8780
8781  MockRead data_reads[] = {
8782    MockRead("HTTP/1.1 200 OK\r\n"),
8783    MockRead(alternate_protocol_http_header.c_str()),
8784    MockRead("hello world"),
8785    MockRead(ASYNC, OK),
8786  };
8787
8788  StaticSocketDataProvider first_transaction(
8789      data_reads, arraysize(data_reads), NULL, 0);
8790  session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
8791
8792  SSLSocketDataProvider ssl(ASYNC, OK);
8793  ssl.SetNextProto(GetParam());
8794  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
8795
8796  scoped_ptr<SpdyFrame> req(
8797      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
8798  MockWrite spdy_writes[] = { CreateMockWrite(*req) };
8799
8800  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
8801  scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
8802  MockRead spdy_reads[] = {
8803    CreateMockRead(*resp),
8804    CreateMockRead(*data),
8805    MockRead(ASYNC, 0, 0),
8806  };
8807
8808  DelayedSocketData spdy_data(
8809      1,  // wait for one write to finish before reading.
8810      spdy_reads, arraysize(spdy_reads),
8811      spdy_writes, arraysize(spdy_writes));
8812  session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
8813
8814  TestCompletionCallback callback;
8815
8816  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8817
8818  scoped_ptr<HttpTransaction> trans(
8819      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8820
8821  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8822  EXPECT_EQ(ERR_IO_PENDING, rv);
8823  EXPECT_EQ(OK, callback.WaitForResult());
8824
8825  const HttpResponseInfo* response = trans->GetResponseInfo();
8826  ASSERT_TRUE(response != NULL);
8827  ASSERT_TRUE(response->headers.get() != NULL);
8828  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8829
8830  std::string response_data;
8831  ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8832  EXPECT_EQ("hello world", response_data);
8833
8834  // Set up an initial SpdySession in the pool to reuse.
8835  HostPortPair host_port_pair("www.google.com", 443);
8836  SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
8837                     kPrivacyModeDisabled);
8838  base::WeakPtr<SpdySession> spdy_session =
8839      CreateSecureSpdySession(session, key, BoundNetLog());
8840
8841  trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8842
8843  rv = trans->Start(&request, callback.callback(), BoundNetLog());
8844  EXPECT_EQ(ERR_IO_PENDING, rv);
8845  EXPECT_EQ(OK, callback.WaitForResult());
8846
8847  response = trans->GetResponseInfo();
8848  ASSERT_TRUE(response != NULL);
8849  ASSERT_TRUE(response->headers.get() != NULL);
8850  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8851  EXPECT_TRUE(response->was_fetched_via_spdy);
8852  EXPECT_TRUE(response->was_npn_negotiated);
8853
8854  ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8855  EXPECT_EQ("hello!", response_data);
8856}
8857
8858// GenerateAuthToken is a mighty big test.
8859// It tests all permutation of GenerateAuthToken behavior:
8860//   - Synchronous and Asynchronous completion.
8861//   - OK or error on completion.
8862//   - Direct connection, non-authenticating proxy, and authenticating proxy.
8863//   - HTTP or HTTPS backend (to include proxy tunneling).
8864//   - Non-authenticating and authenticating backend.
8865//
8866// In all, there are 44 reasonable permuations (for example, if there are
8867// problems generating an auth token for an authenticating proxy, we don't
8868// need to test all permutations of the backend server).
8869//
8870// The test proceeds by going over each of the configuration cases, and
8871// potentially running up to three rounds in each of the tests. The TestConfig
8872// specifies both the configuration for the test as well as the expectations
8873// for the results.
8874TEST_P(HttpNetworkTransactionTest, GenerateAuthToken) {
8875  static const char kServer[] = "http://www.example.com";
8876  static const char kSecureServer[] = "https://www.example.com";
8877  static const char kProxy[] = "myproxy:70";
8878  const int kAuthErr = ERR_INVALID_AUTH_CREDENTIALS;
8879
8880  enum AuthTiming {
8881    AUTH_NONE,
8882    AUTH_SYNC,
8883    AUTH_ASYNC,
8884  };
8885
8886  const MockWrite kGet(
8887      "GET / HTTP/1.1\r\n"
8888      "Host: www.example.com\r\n"
8889      "Connection: keep-alive\r\n\r\n");
8890  const MockWrite kGetProxy(
8891      "GET http://www.example.com/ HTTP/1.1\r\n"
8892      "Host: www.example.com\r\n"
8893      "Proxy-Connection: keep-alive\r\n\r\n");
8894  const MockWrite kGetAuth(
8895      "GET / HTTP/1.1\r\n"
8896      "Host: www.example.com\r\n"
8897      "Connection: keep-alive\r\n"
8898      "Authorization: auth_token\r\n\r\n");
8899  const MockWrite kGetProxyAuth(
8900      "GET http://www.example.com/ HTTP/1.1\r\n"
8901      "Host: www.example.com\r\n"
8902      "Proxy-Connection: keep-alive\r\n"
8903      "Proxy-Authorization: auth_token\r\n\r\n");
8904  const MockWrite kGetAuthThroughProxy(
8905      "GET http://www.example.com/ HTTP/1.1\r\n"
8906      "Host: www.example.com\r\n"
8907      "Proxy-Connection: keep-alive\r\n"
8908      "Authorization: auth_token\r\n\r\n");
8909  const MockWrite kGetAuthWithProxyAuth(
8910      "GET http://www.example.com/ HTTP/1.1\r\n"
8911      "Host: www.example.com\r\n"
8912      "Proxy-Connection: keep-alive\r\n"
8913      "Proxy-Authorization: auth_token\r\n"
8914      "Authorization: auth_token\r\n\r\n");
8915  const MockWrite kConnect(
8916      "CONNECT www.example.com:443 HTTP/1.1\r\n"
8917      "Host: www.example.com\r\n"
8918      "Proxy-Connection: keep-alive\r\n\r\n");
8919  const MockWrite kConnectProxyAuth(
8920      "CONNECT www.example.com:443 HTTP/1.1\r\n"
8921      "Host: www.example.com\r\n"
8922      "Proxy-Connection: keep-alive\r\n"
8923      "Proxy-Authorization: auth_token\r\n\r\n");
8924
8925  const MockRead kSuccess(
8926      "HTTP/1.1 200 OK\r\n"
8927      "Content-Type: text/html; charset=iso-8859-1\r\n"
8928      "Content-Length: 3\r\n\r\n"
8929      "Yes");
8930  const MockRead kFailure(
8931      "Should not be called.");
8932  const MockRead kServerChallenge(
8933      "HTTP/1.1 401 Unauthorized\r\n"
8934      "WWW-Authenticate: Mock realm=server\r\n"
8935      "Content-Type: text/html; charset=iso-8859-1\r\n"
8936      "Content-Length: 14\r\n\r\n"
8937      "Unauthorized\r\n");
8938  const MockRead kProxyChallenge(
8939      "HTTP/1.1 407 Unauthorized\r\n"
8940      "Proxy-Authenticate: Mock realm=proxy\r\n"
8941      "Proxy-Connection: close\r\n"
8942      "Content-Type: text/html; charset=iso-8859-1\r\n"
8943      "Content-Length: 14\r\n\r\n"
8944      "Unauthorized\r\n");
8945  const MockRead kProxyConnected(
8946      "HTTP/1.1 200 Connection Established\r\n\r\n");
8947
8948  // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
8949  // no constructors, but the C++ compiler on Windows warns about
8950  // unspecified data in compound literals. So, moved to using constructors,
8951  // and TestRound's created with the default constructor should not be used.
8952  struct TestRound {
8953    TestRound()
8954        : expected_rv(ERR_UNEXPECTED),
8955          extra_write(NULL),
8956          extra_read(NULL) {
8957    }
8958    TestRound(const MockWrite& write_arg, const MockRead& read_arg,
8959              int expected_rv_arg)
8960        : write(write_arg),
8961          read(read_arg),
8962          expected_rv(expected_rv_arg),
8963          extra_write(NULL),
8964          extra_read(NULL) {
8965    }
8966    TestRound(const MockWrite& write_arg, const MockRead& read_arg,
8967              int expected_rv_arg, const MockWrite* extra_write_arg,
8968              const MockRead* extra_read_arg)
8969        : write(write_arg),
8970          read(read_arg),
8971          expected_rv(expected_rv_arg),
8972          extra_write(extra_write_arg),
8973          extra_read(extra_read_arg) {
8974    }
8975    MockWrite write;
8976    MockRead read;
8977    int expected_rv;
8978    const MockWrite* extra_write;
8979    const MockRead* extra_read;
8980  };
8981
8982  static const int kNoSSL = 500;
8983
8984  struct TestConfig {
8985    const char* proxy_url;
8986    AuthTiming proxy_auth_timing;
8987    int proxy_auth_rv;
8988    const char* server_url;
8989    AuthTiming server_auth_timing;
8990    int server_auth_rv;
8991    int num_auth_rounds;
8992    int first_ssl_round;
8993    TestRound rounds[3];
8994  } test_configs[] = {
8995    // Non-authenticating HTTP server with a direct connection.
8996    { NULL, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
8997      { TestRound(kGet, kSuccess, OK)}},
8998    // Authenticating HTTP server with a direct connection.
8999    { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
9000      { TestRound(kGet, kServerChallenge, OK),
9001        TestRound(kGetAuth, kSuccess, OK)}},
9002    { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
9003      { TestRound(kGet, kServerChallenge, OK),
9004        TestRound(kGetAuth, kFailure, kAuthErr)}},
9005    { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
9006      { TestRound(kGet, kServerChallenge, OK),
9007        TestRound(kGetAuth, kSuccess, OK)}},
9008    { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
9009      { TestRound(kGet, kServerChallenge, OK),
9010        TestRound(kGetAuth, kFailure, kAuthErr)}},
9011    // Non-authenticating HTTP server through a non-authenticating proxy.
9012    { kProxy, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
9013      { TestRound(kGetProxy, kSuccess, OK)}},
9014    // Authenticating HTTP server through a non-authenticating proxy.
9015    { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
9016      { TestRound(kGetProxy, kServerChallenge, OK),
9017        TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
9018    { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
9019      { TestRound(kGetProxy, kServerChallenge, OK),
9020        TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
9021    { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
9022      { TestRound(kGetProxy, kServerChallenge, OK),
9023        TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
9024    { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
9025      { TestRound(kGetProxy, kServerChallenge, OK),
9026        TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
9027    // Non-authenticating HTTP server through an authenticating proxy.
9028    { kProxy, AUTH_SYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
9029      { TestRound(kGetProxy, kProxyChallenge, OK),
9030        TestRound(kGetProxyAuth, kSuccess, OK)}},
9031    { kProxy, AUTH_SYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
9032      { TestRound(kGetProxy, kProxyChallenge, OK),
9033        TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
9034    { kProxy, AUTH_ASYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
9035      { TestRound(kGetProxy, kProxyChallenge, OK),
9036        TestRound(kGetProxyAuth, kSuccess, OK)}},
9037    { kProxy, AUTH_ASYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
9038      { TestRound(kGetProxy, kProxyChallenge, OK),
9039        TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
9040    // Authenticating HTTP server through an authenticating proxy.
9041    { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
9042      { TestRound(kGetProxy, kProxyChallenge, OK),
9043        TestRound(kGetProxyAuth, kServerChallenge, OK),
9044        TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
9045    { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
9046      { TestRound(kGetProxy, kProxyChallenge, OK),
9047        TestRound(kGetProxyAuth, kServerChallenge, OK),
9048        TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
9049    { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
9050      { TestRound(kGetProxy, kProxyChallenge, OK),
9051        TestRound(kGetProxyAuth, kServerChallenge, OK),
9052        TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
9053    { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
9054      { TestRound(kGetProxy, kProxyChallenge, OK),
9055        TestRound(kGetProxyAuth, kServerChallenge, OK),
9056        TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
9057    { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
9058      { TestRound(kGetProxy, kProxyChallenge, OK),
9059        TestRound(kGetProxyAuth, kServerChallenge, OK),
9060        TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
9061    { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
9062      { TestRound(kGetProxy, kProxyChallenge, OK),
9063        TestRound(kGetProxyAuth, kServerChallenge, OK),
9064        TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
9065    { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
9066      { TestRound(kGetProxy, kProxyChallenge, OK),
9067        TestRound(kGetProxyAuth, kServerChallenge, OK),
9068        TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
9069    { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
9070      { TestRound(kGetProxy, kProxyChallenge, OK),
9071        TestRound(kGetProxyAuth, kServerChallenge, OK),
9072        TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
9073    // Non-authenticating HTTPS server with a direct connection.
9074    { NULL, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
9075      { TestRound(kGet, kSuccess, OK)}},
9076    // Authenticating HTTPS server with a direct connection.
9077    { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
9078      { TestRound(kGet, kServerChallenge, OK),
9079        TestRound(kGetAuth, kSuccess, OK)}},
9080    { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
9081      { TestRound(kGet, kServerChallenge, OK),
9082        TestRound(kGetAuth, kFailure, kAuthErr)}},
9083    { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
9084      { TestRound(kGet, kServerChallenge, OK),
9085        TestRound(kGetAuth, kSuccess, OK)}},
9086    { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
9087      { TestRound(kGet, kServerChallenge, OK),
9088        TestRound(kGetAuth, kFailure, kAuthErr)}},
9089    // Non-authenticating HTTPS server with a non-authenticating proxy.
9090    { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
9091      { TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
9092    // Authenticating HTTPS server through a non-authenticating proxy.
9093    { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
9094      { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
9095        TestRound(kGetAuth, kSuccess, OK)}},
9096    { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
9097      { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
9098        TestRound(kGetAuth, kFailure, kAuthErr)}},
9099    { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
9100      { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
9101        TestRound(kGetAuth, kSuccess, OK)}},
9102    { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
9103      { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
9104        TestRound(kGetAuth, kFailure, kAuthErr)}},
9105    // Non-Authenticating HTTPS server through an authenticating proxy.
9106    { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
9107      { TestRound(kConnect, kProxyChallenge, OK),
9108        TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
9109    { kProxy, AUTH_SYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
9110      { TestRound(kConnect, kProxyChallenge, OK),
9111        TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
9112    { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
9113      { TestRound(kConnect, kProxyChallenge, OK),
9114        TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
9115    { kProxy, AUTH_ASYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
9116      { TestRound(kConnect, kProxyChallenge, OK),
9117        TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
9118    // Authenticating HTTPS server through an authenticating proxy.
9119    { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
9120      { TestRound(kConnect, kProxyChallenge, OK),
9121        TestRound(kConnectProxyAuth, kProxyConnected, OK,
9122                  &kGet, &kServerChallenge),
9123        TestRound(kGetAuth, kSuccess, OK)}},
9124    { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
9125      { TestRound(kConnect, kProxyChallenge, OK),
9126        TestRound(kConnectProxyAuth, kProxyConnected, OK,
9127                  &kGet, &kServerChallenge),
9128        TestRound(kGetAuth, kFailure, kAuthErr)}},
9129    { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
9130      { TestRound(kConnect, kProxyChallenge, OK),
9131        TestRound(kConnectProxyAuth, kProxyConnected, OK,
9132                  &kGet, &kServerChallenge),
9133        TestRound(kGetAuth, kSuccess, OK)}},
9134    { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
9135      { TestRound(kConnect, kProxyChallenge, OK),
9136        TestRound(kConnectProxyAuth, kProxyConnected, OK,
9137                  &kGet, &kServerChallenge),
9138        TestRound(kGetAuth, kFailure, kAuthErr)}},
9139    { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
9140      { TestRound(kConnect, kProxyChallenge, OK),
9141        TestRound(kConnectProxyAuth, kProxyConnected, OK,
9142                  &kGet, &kServerChallenge),
9143        TestRound(kGetAuth, kSuccess, OK)}},
9144    { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
9145      { TestRound(kConnect, kProxyChallenge, OK),
9146        TestRound(kConnectProxyAuth, kProxyConnected, OK,
9147                  &kGet, &kServerChallenge),
9148        TestRound(kGetAuth, kFailure, kAuthErr)}},
9149    { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
9150      { TestRound(kConnect, kProxyChallenge, OK),
9151        TestRound(kConnectProxyAuth, kProxyConnected, OK,
9152                  &kGet, &kServerChallenge),
9153        TestRound(kGetAuth, kSuccess, OK)}},
9154    { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
9155      { TestRound(kConnect, kProxyChallenge, OK),
9156        TestRound(kConnectProxyAuth, kProxyConnected, OK,
9157                  &kGet, &kServerChallenge),
9158        TestRound(kGetAuth, kFailure, kAuthErr)}},
9159  };
9160
9161  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_configs); ++i) {
9162    HttpAuthHandlerMock::Factory* auth_factory(
9163        new HttpAuthHandlerMock::Factory());
9164    session_deps_.http_auth_handler_factory.reset(auth_factory);
9165    const TestConfig& test_config = test_configs[i];
9166
9167    // Set up authentication handlers as necessary.
9168    if (test_config.proxy_auth_timing != AUTH_NONE) {
9169      for (int n = 0; n < 2; n++) {
9170        HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
9171        std::string auth_challenge = "Mock realm=proxy";
9172        GURL origin(test_config.proxy_url);
9173        HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
9174                                               auth_challenge.end());
9175        auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_PROXY,
9176                                        origin, BoundNetLog());
9177        auth_handler->SetGenerateExpectation(
9178            test_config.proxy_auth_timing == AUTH_ASYNC,
9179            test_config.proxy_auth_rv);
9180        auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_PROXY);
9181      }
9182    }
9183    if (test_config.server_auth_timing != AUTH_NONE) {
9184      HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
9185      std::string auth_challenge = "Mock realm=server";
9186      GURL origin(test_config.server_url);
9187      HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
9188                                             auth_challenge.end());
9189      auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
9190                                      origin, BoundNetLog());
9191      auth_handler->SetGenerateExpectation(
9192          test_config.server_auth_timing == AUTH_ASYNC,
9193          test_config.server_auth_rv);
9194      auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
9195    }
9196    if (test_config.proxy_url) {
9197      session_deps_.proxy_service.reset(
9198          ProxyService::CreateFixed(test_config.proxy_url));
9199    } else {
9200      session_deps_.proxy_service.reset(ProxyService::CreateDirect());
9201    }
9202
9203    HttpRequestInfo request;
9204    request.method = "GET";
9205    request.url = GURL(test_config.server_url);
9206    request.load_flags = 0;
9207
9208    scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9209    HttpNetworkTransaction trans(
9210        DEFAULT_PRIORITY, CreateSession(&session_deps_));
9211
9212    for (int round = 0; round < test_config.num_auth_rounds; ++round) {
9213      const TestRound& read_write_round = test_config.rounds[round];
9214
9215      // Set up expected reads and writes.
9216      MockRead reads[2];
9217      reads[0] = read_write_round.read;
9218      size_t length_reads = 1;
9219      if (read_write_round.extra_read) {
9220        reads[1] = *read_write_round.extra_read;
9221        length_reads = 2;
9222      }
9223
9224      MockWrite writes[2];
9225      writes[0] = read_write_round.write;
9226      size_t length_writes = 1;
9227      if (read_write_round.extra_write) {
9228        writes[1] = *read_write_round.extra_write;
9229        length_writes = 2;
9230      }
9231      StaticSocketDataProvider data_provider(
9232          reads, length_reads, writes, length_writes);
9233      session_deps_.socket_factory->AddSocketDataProvider(&data_provider);
9234
9235      // Add an SSL sequence if necessary.
9236      SSLSocketDataProvider ssl_socket_data_provider(SYNCHRONOUS, OK);
9237      if (round >= test_config.first_ssl_round)
9238        session_deps_.socket_factory->AddSSLSocketDataProvider(
9239            &ssl_socket_data_provider);
9240
9241      // Start or restart the transaction.
9242      TestCompletionCallback callback;
9243      int rv;
9244      if (round == 0) {
9245        rv = trans.Start(&request, callback.callback(), BoundNetLog());
9246      } else {
9247        rv = trans.RestartWithAuth(
9248            AuthCredentials(kFoo, kBar), callback.callback());
9249      }
9250      if (rv == ERR_IO_PENDING)
9251        rv = callback.WaitForResult();
9252
9253      // Compare results with expected data.
9254      EXPECT_EQ(read_write_round.expected_rv, rv);
9255      const HttpResponseInfo* response = trans.GetResponseInfo();
9256      if (read_write_round.expected_rv == OK) {
9257        ASSERT_TRUE(response != NULL);
9258      } else {
9259        EXPECT_TRUE(response == NULL);
9260        EXPECT_EQ(round + 1, test_config.num_auth_rounds);
9261        continue;
9262      }
9263      if (round + 1 < test_config.num_auth_rounds) {
9264        EXPECT_FALSE(response->auth_challenge.get() == NULL);
9265      } else {
9266        EXPECT_TRUE(response->auth_challenge.get() == NULL);
9267      }
9268    }
9269  }
9270}
9271
9272TEST_P(HttpNetworkTransactionTest, MultiRoundAuth) {
9273  // Do multi-round authentication and make sure it works correctly.
9274  HttpAuthHandlerMock::Factory* auth_factory(
9275      new HttpAuthHandlerMock::Factory());
9276  session_deps_.http_auth_handler_factory.reset(auth_factory);
9277  session_deps_.proxy_service.reset(ProxyService::CreateDirect());
9278  session_deps_.host_resolver->rules()->AddRule("www.example.com", "10.0.0.1");
9279  session_deps_.host_resolver->set_synchronous_mode(true);
9280
9281  HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
9282  auth_handler->set_connection_based(true);
9283  std::string auth_challenge = "Mock realm=server";
9284  GURL origin("http://www.example.com");
9285  HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
9286                                         auth_challenge.end());
9287  auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
9288                                  origin, BoundNetLog());
9289  auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
9290
9291  int rv = OK;
9292  const HttpResponseInfo* response = NULL;
9293  HttpRequestInfo request;
9294  request.method = "GET";
9295  request.url = origin;
9296  request.load_flags = 0;
9297
9298  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9299
9300  // Use a TCP Socket Pool with only one connection per group. This is used
9301  // to validate that the TCP socket is not released to the pool between
9302  // each round of multi-round authentication.
9303  HttpNetworkSessionPeer session_peer(session);
9304  ClientSocketPoolHistograms transport_pool_histograms("SmallTCP");
9305  TransportClientSocketPool* transport_pool = new TransportClientSocketPool(
9306      50,  // Max sockets for pool
9307      1,   // Max sockets per group
9308      &transport_pool_histograms,
9309      session_deps_.host_resolver.get(),
9310      session_deps_.socket_factory.get(),
9311      session_deps_.net_log);
9312  MockClientSocketPoolManager* mock_pool_manager =
9313      new MockClientSocketPoolManager;
9314  mock_pool_manager->SetTransportSocketPool(transport_pool);
9315  session_peer.SetClientSocketPoolManager(mock_pool_manager);
9316
9317  scoped_ptr<HttpTransaction> trans(
9318      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9319  TestCompletionCallback callback;
9320
9321  const MockWrite kGet(
9322      "GET / HTTP/1.1\r\n"
9323      "Host: www.example.com\r\n"
9324      "Connection: keep-alive\r\n\r\n");
9325  const MockWrite kGetAuth(
9326      "GET / HTTP/1.1\r\n"
9327      "Host: www.example.com\r\n"
9328      "Connection: keep-alive\r\n"
9329      "Authorization: auth_token\r\n\r\n");
9330
9331  const MockRead kServerChallenge(
9332      "HTTP/1.1 401 Unauthorized\r\n"
9333      "WWW-Authenticate: Mock realm=server\r\n"
9334      "Content-Type: text/html; charset=iso-8859-1\r\n"
9335      "Content-Length: 14\r\n\r\n"
9336      "Unauthorized\r\n");
9337  const MockRead kSuccess(
9338      "HTTP/1.1 200 OK\r\n"
9339      "Content-Type: text/html; charset=iso-8859-1\r\n"
9340      "Content-Length: 3\r\n\r\n"
9341      "Yes");
9342
9343  MockWrite writes[] = {
9344    // First round
9345    kGet,
9346    // Second round
9347    kGetAuth,
9348    // Third round
9349    kGetAuth,
9350    // Fourth round
9351    kGetAuth,
9352    // Competing request
9353    kGet,
9354  };
9355  MockRead reads[] = {
9356    // First round
9357    kServerChallenge,
9358    // Second round
9359    kServerChallenge,
9360    // Third round
9361    kServerChallenge,
9362    // Fourth round
9363    kSuccess,
9364    // Competing response
9365    kSuccess,
9366  };
9367  StaticSocketDataProvider data_provider(reads, arraysize(reads),
9368                                         writes, arraysize(writes));
9369  session_deps_.socket_factory->AddSocketDataProvider(&data_provider);
9370
9371  const char* const kSocketGroup = "www.example.com:80";
9372
9373  // First round of authentication.
9374  auth_handler->SetGenerateExpectation(false, OK);
9375  rv = trans->Start(&request, callback.callback(), BoundNetLog());
9376  if (rv == ERR_IO_PENDING)
9377    rv = callback.WaitForResult();
9378  EXPECT_EQ(OK, rv);
9379  response = trans->GetResponseInfo();
9380  ASSERT_TRUE(response != NULL);
9381  EXPECT_FALSE(response->auth_challenge.get() == NULL);
9382  EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
9383
9384  // In between rounds, another request comes in for the same domain.
9385  // It should not be able to grab the TCP socket that trans has already
9386  // claimed.
9387  scoped_ptr<HttpTransaction> trans_compete(
9388      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9389  TestCompletionCallback callback_compete;
9390  rv = trans_compete->Start(
9391      &request, callback_compete.callback(), BoundNetLog());
9392  EXPECT_EQ(ERR_IO_PENDING, rv);
9393  // callback_compete.WaitForResult at this point would stall forever,
9394  // since the HttpNetworkTransaction does not release the request back to
9395  // the pool until after authentication completes.
9396
9397  // Second round of authentication.
9398  auth_handler->SetGenerateExpectation(false, OK);
9399  rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
9400  if (rv == ERR_IO_PENDING)
9401    rv = callback.WaitForResult();
9402  EXPECT_EQ(OK, rv);
9403  response = trans->GetResponseInfo();
9404  ASSERT_TRUE(response != NULL);
9405  EXPECT_TRUE(response->auth_challenge.get() == NULL);
9406  EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
9407
9408  // Third round of authentication.
9409  auth_handler->SetGenerateExpectation(false, OK);
9410  rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
9411  if (rv == ERR_IO_PENDING)
9412    rv = callback.WaitForResult();
9413  EXPECT_EQ(OK, rv);
9414  response = trans->GetResponseInfo();
9415  ASSERT_TRUE(response != NULL);
9416  EXPECT_TRUE(response->auth_challenge.get() == NULL);
9417  EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
9418
9419  // Fourth round of authentication, which completes successfully.
9420  auth_handler->SetGenerateExpectation(false, OK);
9421  rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
9422  if (rv == ERR_IO_PENDING)
9423    rv = callback.WaitForResult();
9424  EXPECT_EQ(OK, rv);
9425  response = trans->GetResponseInfo();
9426  ASSERT_TRUE(response != NULL);
9427  EXPECT_TRUE(response->auth_challenge.get() == NULL);
9428  EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
9429
9430  // Read the body since the fourth round was successful. This will also
9431  // release the socket back to the pool.
9432  scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(50));
9433  rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
9434  if (rv == ERR_IO_PENDING)
9435    rv = callback.WaitForResult();
9436  EXPECT_EQ(3, rv);
9437  rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
9438  EXPECT_EQ(0, rv);
9439  // There are still 0 idle sockets, since the trans_compete transaction
9440  // will be handed it immediately after trans releases it to the group.
9441  EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
9442
9443  // The competing request can now finish. Wait for the headers and then
9444  // read the body.
9445  rv = callback_compete.WaitForResult();
9446  EXPECT_EQ(OK, rv);
9447  rv = trans_compete->Read(io_buf.get(), io_buf->size(), callback.callback());
9448  if (rv == ERR_IO_PENDING)
9449    rv = callback.WaitForResult();
9450  EXPECT_EQ(3, rv);
9451  rv = trans_compete->Read(io_buf.get(), io_buf->size(), callback.callback());
9452  EXPECT_EQ(0, rv);
9453
9454  // Finally, the socket is released to the group.
9455  EXPECT_EQ(1, transport_pool->IdleSocketCountInGroup(kSocketGroup));
9456}
9457
9458// This tests the case that a request is issued via http instead of spdy after
9459// npn is negotiated.
9460TEST_P(HttpNetworkTransactionTest, NpnWithHttpOverSSL) {
9461  HttpStreamFactory::set_use_alternate_protocols(true);
9462  std::vector<NextProto> next_protos;
9463  next_protos.push_back(kProtoHTTP11);
9464  HttpStreamFactory::SetNextProtos(next_protos);
9465  HttpRequestInfo request;
9466  request.method = "GET";
9467  request.url = GURL("https://www.google.com/");
9468  request.load_flags = 0;
9469
9470  MockWrite data_writes[] = {
9471    MockWrite("GET / HTTP/1.1\r\n"
9472              "Host: www.google.com\r\n"
9473              "Connection: keep-alive\r\n\r\n"),
9474  };
9475
9476  std::string alternate_protocol_http_header =
9477      GetAlternateProtocolHttpHeader();
9478
9479  MockRead data_reads[] = {
9480    MockRead("HTTP/1.1 200 OK\r\n"),
9481    MockRead(alternate_protocol_http_header.c_str()),
9482    MockRead("hello world"),
9483    MockRead(SYNCHRONOUS, OK),
9484  };
9485
9486  SSLSocketDataProvider ssl(ASYNC, OK);
9487  ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
9488  ssl.next_proto = "http/1.1";
9489  ssl.protocol_negotiated = kProtoHTTP11;
9490
9491  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9492
9493  StaticSocketDataProvider data(data_reads, arraysize(data_reads),
9494                                data_writes, arraysize(data_writes));
9495  session_deps_.socket_factory->AddSocketDataProvider(&data);
9496
9497  TestCompletionCallback callback;
9498
9499  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9500  scoped_ptr<HttpTransaction> trans(
9501      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9502
9503  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9504
9505  EXPECT_EQ(ERR_IO_PENDING, rv);
9506  EXPECT_EQ(OK, callback.WaitForResult());
9507
9508  const HttpResponseInfo* response = trans->GetResponseInfo();
9509  ASSERT_TRUE(response != NULL);
9510  ASSERT_TRUE(response->headers.get() != NULL);
9511  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9512
9513  std::string response_data;
9514  ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9515  EXPECT_EQ("hello world", response_data);
9516
9517  EXPECT_FALSE(response->was_fetched_via_spdy);
9518  EXPECT_TRUE(response->was_npn_negotiated);
9519}
9520
9521TEST_P(HttpNetworkTransactionTest, SpdyPostNPNServerHangup) {
9522  // Simulate the SSL handshake completing with an NPN negotiation
9523  // followed by an immediate server closing of the socket.
9524  // Fix crash:  http://crbug.com/46369
9525  HttpStreamFactory::set_use_alternate_protocols(true);
9526  HttpStreamFactory::SetNextProtos(SpdyNextProtos());
9527
9528  HttpRequestInfo request;
9529  request.method = "GET";
9530  request.url = GURL("https://www.google.com/");
9531  request.load_flags = 0;
9532
9533  SSLSocketDataProvider ssl(ASYNC, OK);
9534  ssl.SetNextProto(GetParam());
9535  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9536
9537  scoped_ptr<SpdyFrame> req(
9538      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
9539  MockWrite spdy_writes[] = { CreateMockWrite(*req) };
9540
9541  MockRead spdy_reads[] = {
9542    MockRead(SYNCHRONOUS, 0, 0)   // Not async - return 0 immediately.
9543  };
9544
9545  DelayedSocketData spdy_data(
9546      0,  // don't wait in this case, immediate hangup.
9547      spdy_reads, arraysize(spdy_reads),
9548      spdy_writes, arraysize(spdy_writes));
9549  session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
9550
9551  TestCompletionCallback callback;
9552
9553  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9554  scoped_ptr<HttpTransaction> trans(
9555      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9556
9557  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9558  EXPECT_EQ(ERR_IO_PENDING, rv);
9559  EXPECT_EQ(ERR_CONNECTION_CLOSED, callback.WaitForResult());
9560}
9561
9562// A subclass of HttpAuthHandlerMock that records the request URL when
9563// it gets it. This is needed since the auth handler may get destroyed
9564// before we get a chance to query it.
9565class UrlRecordingHttpAuthHandlerMock : public HttpAuthHandlerMock {
9566 public:
9567  explicit UrlRecordingHttpAuthHandlerMock(GURL* url) : url_(url) {}
9568
9569  virtual ~UrlRecordingHttpAuthHandlerMock() {}
9570
9571 protected:
9572  virtual int GenerateAuthTokenImpl(const AuthCredentials* credentials,
9573                                    const HttpRequestInfo* request,
9574                                    const CompletionCallback& callback,
9575                                    std::string* auth_token) OVERRIDE {
9576    *url_ = request->url;
9577    return HttpAuthHandlerMock::GenerateAuthTokenImpl(
9578        credentials, request, callback, auth_token);
9579  }
9580
9581 private:
9582  GURL* url_;
9583};
9584
9585TEST_P(HttpNetworkTransactionTest, SpdyAlternateProtocolThroughProxy) {
9586  // This test ensures that the URL passed into the proxy is upgraded
9587  // to https when doing an Alternate Protocol upgrade.
9588  HttpStreamFactory::set_use_alternate_protocols(true);
9589  HttpStreamFactory::SetNextProtos(SpdyNextProtos());
9590
9591  session_deps_.proxy_service.reset(
9592      ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
9593  CapturingNetLog net_log;
9594  session_deps_.net_log = &net_log;
9595  GURL request_url;
9596  {
9597    HttpAuthHandlerMock::Factory* auth_factory =
9598        new HttpAuthHandlerMock::Factory();
9599    UrlRecordingHttpAuthHandlerMock* auth_handler =
9600        new UrlRecordingHttpAuthHandlerMock(&request_url);
9601    auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_PROXY);
9602    auth_factory->set_do_init_from_challenge(true);
9603    session_deps_.http_auth_handler_factory.reset(auth_factory);
9604  }
9605
9606  HttpRequestInfo request;
9607  request.method = "GET";
9608  request.url = GURL("http://www.google.com");
9609  request.load_flags = 0;
9610
9611  // First round goes unauthenticated through the proxy.
9612  MockWrite data_writes_1[] = {
9613    MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
9614              "Host: www.google.com\r\n"
9615              "Proxy-Connection: keep-alive\r\n"
9616              "\r\n"),
9617  };
9618  MockRead data_reads_1[] = {
9619    MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
9620    MockRead("HTTP/1.1 200 OK\r\n"
9621             "Alternate-Protocol: 443:npn-spdy/2\r\n"
9622             "Proxy-Connection: close\r\n"
9623             "\r\n"),
9624  };
9625  StaticSocketDataProvider data_1(data_reads_1, arraysize(data_reads_1),
9626                                  data_writes_1, arraysize(data_writes_1));
9627
9628  // Second round tries to tunnel to www.google.com due to the
9629  // Alternate-Protocol announcement in the first round. It fails due
9630  // to a proxy authentication challenge.
9631  // After the failure, a tunnel is established to www.google.com using
9632  // Proxy-Authorization headers. There is then a SPDY request round.
9633  //
9634  // NOTE: Despite the "Proxy-Connection: Close", these are done on the
9635  // same MockTCPClientSocket since the underlying HttpNetworkClientSocket
9636  // does a Disconnect and Connect on the same socket, rather than trying
9637  // to obtain a new one.
9638  //
9639  // NOTE: Originally, the proxy response to the second CONNECT request
9640  // simply returned another 407 so the unit test could skip the SSL connection
9641  // establishment and SPDY framing issues. Alas, the
9642  // retry-http-when-alternate-protocol fails logic kicks in, which was more
9643  // complicated to set up expectations for than the SPDY session.
9644
9645  scoped_ptr<SpdyFrame> req(
9646      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
9647  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
9648  scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
9649
9650  MockWrite data_writes_2[] = {
9651    // First connection attempt without Proxy-Authorization.
9652    MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
9653              "Host: www.google.com\r\n"
9654              "Proxy-Connection: keep-alive\r\n"
9655              "\r\n"),
9656
9657    // Second connection attempt with Proxy-Authorization.
9658    MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
9659              "Host: www.google.com\r\n"
9660              "Proxy-Connection: keep-alive\r\n"
9661              "Proxy-Authorization: auth_token\r\n"
9662              "\r\n"),
9663
9664    // SPDY request
9665    CreateMockWrite(*req),
9666  };
9667  const char kRejectConnectResponse[] = ("HTTP/1.1 407 Unauthorized\r\n"
9668                                         "Proxy-Authenticate: Mock\r\n"
9669                                         "Proxy-Connection: close\r\n"
9670                                         "\r\n");
9671  const char kAcceptConnectResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
9672  MockRead data_reads_2[] = {
9673    // First connection attempt fails
9674    MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ, 1),
9675    MockRead(ASYNC, kRejectConnectResponse,
9676             arraysize(kRejectConnectResponse) - 1, 1),
9677
9678    // Second connection attempt passes
9679    MockRead(ASYNC, kAcceptConnectResponse,
9680             arraysize(kAcceptConnectResponse) -1, 4),
9681
9682    // SPDY response
9683    CreateMockRead(*resp.get(), 6),
9684    CreateMockRead(*data.get(), 6),
9685    MockRead(ASYNC, 0, 0, 6),
9686  };
9687  OrderedSocketData data_2(
9688      data_reads_2, arraysize(data_reads_2),
9689      data_writes_2, arraysize(data_writes_2));
9690
9691  SSLSocketDataProvider ssl(ASYNC, OK);
9692  ssl.SetNextProto(GetParam());
9693
9694  MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
9695  StaticSocketDataProvider hanging_non_alternate_protocol_socket(
9696      NULL, 0, NULL, 0);
9697  hanging_non_alternate_protocol_socket.set_connect_data(
9698      never_finishing_connect);
9699
9700  session_deps_.socket_factory->AddSocketDataProvider(&data_1);
9701  session_deps_.socket_factory->AddSocketDataProvider(&data_2);
9702  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9703  session_deps_.socket_factory->AddSocketDataProvider(
9704      &hanging_non_alternate_protocol_socket);
9705  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9706
9707  // First round should work and provide the Alternate-Protocol state.
9708  TestCompletionCallback callback_1;
9709  scoped_ptr<HttpTransaction> trans_1(
9710      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9711  int rv = trans_1->Start(&request, callback_1.callback(), BoundNetLog());
9712  EXPECT_EQ(ERR_IO_PENDING, rv);
9713  EXPECT_EQ(OK, callback_1.WaitForResult());
9714
9715  // Second round should attempt a tunnel connect and get an auth challenge.
9716  TestCompletionCallback callback_2;
9717  scoped_ptr<HttpTransaction> trans_2(
9718      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9719  rv = trans_2->Start(&request, callback_2.callback(), BoundNetLog());
9720  EXPECT_EQ(ERR_IO_PENDING, rv);
9721  EXPECT_EQ(OK, callback_2.WaitForResult());
9722  const HttpResponseInfo* response = trans_2->GetResponseInfo();
9723  ASSERT_TRUE(response != NULL);
9724  ASSERT_FALSE(response->auth_challenge.get() == NULL);
9725
9726  // Restart with auth. Tunnel should work and response received.
9727  TestCompletionCallback callback_3;
9728  rv = trans_2->RestartWithAuth(
9729      AuthCredentials(kFoo, kBar), callback_3.callback());
9730  EXPECT_EQ(ERR_IO_PENDING, rv);
9731  EXPECT_EQ(OK, callback_3.WaitForResult());
9732
9733  // After all that work, these two lines (or actually, just the scheme) are
9734  // what this test is all about. Make sure it happens correctly.
9735  EXPECT_EQ("https", request_url.scheme());
9736  EXPECT_EQ("www.google.com", request_url.host());
9737
9738  LoadTimingInfo load_timing_info;
9739  EXPECT_TRUE(trans_2->GetLoadTimingInfo(&load_timing_info));
9740  TestLoadTimingNotReusedWithPac(load_timing_info,
9741                                 CONNECT_TIMING_HAS_SSL_TIMES);
9742}
9743
9744// Test that if we cancel the transaction as the connection is completing, that
9745// everything tears down correctly.
9746TEST_P(HttpNetworkTransactionTest, SimpleCancel) {
9747  // Setup everything about the connection to complete synchronously, so that
9748  // after calling HttpNetworkTransaction::Start, the only thing we're waiting
9749  // for is the callback from the HttpStreamRequest.
9750  // Then cancel the transaction.
9751  // Verify that we don't crash.
9752  MockConnect mock_connect(SYNCHRONOUS, OK);
9753  MockRead data_reads[] = {
9754    MockRead(SYNCHRONOUS, "HTTP/1.0 200 OK\r\n\r\n"),
9755    MockRead(SYNCHRONOUS, "hello world"),
9756    MockRead(SYNCHRONOUS, OK),
9757  };
9758
9759  HttpRequestInfo request;
9760  request.method = "GET";
9761  request.url = GURL("http://www.google.com/");
9762  request.load_flags = 0;
9763
9764  session_deps_.host_resolver->set_synchronous_mode(true);
9765  scoped_ptr<HttpTransaction> trans(
9766      new HttpNetworkTransaction(DEFAULT_PRIORITY,
9767                                 CreateSession(&session_deps_)));
9768
9769  StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
9770  data.set_connect_data(mock_connect);
9771  session_deps_.socket_factory->AddSocketDataProvider(&data);
9772
9773  TestCompletionCallback callback;
9774
9775  CapturingBoundNetLog log;
9776  int rv = trans->Start(&request, callback.callback(), log.bound());
9777  EXPECT_EQ(ERR_IO_PENDING, rv);
9778  trans.reset();  // Cancel the transaction here.
9779
9780  base::MessageLoop::current()->RunUntilIdle();
9781}
9782
9783// Test a basic GET request through a proxy.
9784TEST_P(HttpNetworkTransactionTest, ProxyGet) {
9785  session_deps_.proxy_service.reset(
9786      ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
9787  CapturingBoundNetLog log;
9788  session_deps_.net_log = log.bound().net_log();
9789  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9790
9791  HttpRequestInfo request;
9792  request.method = "GET";
9793  request.url = GURL("http://www.google.com/");
9794
9795  MockWrite data_writes1[] = {
9796    MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
9797              "Host: www.google.com\r\n"
9798              "Proxy-Connection: keep-alive\r\n\r\n"),
9799  };
9800
9801  MockRead data_reads1[] = {
9802    MockRead("HTTP/1.1 200 OK\r\n"),
9803    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
9804    MockRead("Content-Length: 100\r\n\r\n"),
9805    MockRead(SYNCHRONOUS, OK),
9806  };
9807
9808  StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
9809                                 data_writes1, arraysize(data_writes1));
9810  session_deps_.socket_factory->AddSocketDataProvider(&data1);
9811
9812  TestCompletionCallback callback1;
9813
9814  scoped_ptr<HttpTransaction> trans(
9815      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9816
9817  int rv = trans->Start(&request, callback1.callback(), log.bound());
9818  EXPECT_EQ(ERR_IO_PENDING, rv);
9819
9820  rv = callback1.WaitForResult();
9821  EXPECT_EQ(OK, rv);
9822
9823  const HttpResponseInfo* response = trans->GetResponseInfo();
9824  ASSERT_TRUE(response != NULL);
9825
9826  EXPECT_TRUE(response->headers->IsKeepAlive());
9827  EXPECT_EQ(200, response->headers->response_code());
9828  EXPECT_EQ(100, response->headers->GetContentLength());
9829  EXPECT_TRUE(response->was_fetched_via_proxy);
9830  EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
9831
9832  LoadTimingInfo load_timing_info;
9833  EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
9834  TestLoadTimingNotReusedWithPac(load_timing_info,
9835                                 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
9836}
9837
9838// Test a basic HTTPS GET request through a proxy.
9839TEST_P(HttpNetworkTransactionTest, ProxyTunnelGet) {
9840  session_deps_.proxy_service.reset(
9841      ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
9842  CapturingBoundNetLog log;
9843  session_deps_.net_log = log.bound().net_log();
9844  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9845
9846  HttpRequestInfo request;
9847  request.method = "GET";
9848  request.url = GURL("https://www.google.com/");
9849
9850  // Since we have proxy, should try to establish tunnel.
9851  MockWrite data_writes1[] = {
9852    MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
9853              "Host: www.google.com\r\n"
9854              "Proxy-Connection: keep-alive\r\n\r\n"),
9855
9856    MockWrite("GET / HTTP/1.1\r\n"
9857              "Host: www.google.com\r\n"
9858              "Connection: keep-alive\r\n\r\n"),
9859  };
9860
9861  MockRead data_reads1[] = {
9862    MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
9863
9864    MockRead("HTTP/1.1 200 OK\r\n"),
9865    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
9866    MockRead("Content-Length: 100\r\n\r\n"),
9867    MockRead(SYNCHRONOUS, OK),
9868  };
9869
9870  StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
9871                                 data_writes1, arraysize(data_writes1));
9872  session_deps_.socket_factory->AddSocketDataProvider(&data1);
9873  SSLSocketDataProvider ssl(ASYNC, OK);
9874  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9875
9876  TestCompletionCallback callback1;
9877
9878  scoped_ptr<HttpTransaction> trans(
9879      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9880
9881  int rv = trans->Start(&request, callback1.callback(), log.bound());
9882  EXPECT_EQ(ERR_IO_PENDING, rv);
9883
9884  rv = callback1.WaitForResult();
9885  EXPECT_EQ(OK, rv);
9886  net::CapturingNetLog::CapturedEntryList entries;
9887  log.GetEntries(&entries);
9888  size_t pos = ExpectLogContainsSomewhere(
9889      entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
9890      NetLog::PHASE_NONE);
9891  ExpectLogContainsSomewhere(
9892      entries, pos,
9893      NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
9894      NetLog::PHASE_NONE);
9895
9896  const HttpResponseInfo* response = trans->GetResponseInfo();
9897  ASSERT_TRUE(response != NULL);
9898
9899  EXPECT_TRUE(response->headers->IsKeepAlive());
9900  EXPECT_EQ(200, response->headers->response_code());
9901  EXPECT_EQ(100, response->headers->GetContentLength());
9902  EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
9903  EXPECT_TRUE(response->was_fetched_via_proxy);
9904
9905  LoadTimingInfo load_timing_info;
9906  EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
9907  TestLoadTimingNotReusedWithPac(load_timing_info,
9908                                 CONNECT_TIMING_HAS_SSL_TIMES);
9909}
9910
9911// Test a basic HTTPS GET request through a proxy, but the server hangs up
9912// while establishing the tunnel.
9913TEST_P(HttpNetworkTransactionTest, ProxyTunnelGetHangup) {
9914  session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
9915  CapturingBoundNetLog log;
9916  session_deps_.net_log = log.bound().net_log();
9917  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9918
9919  HttpRequestInfo request;
9920  request.method = "GET";
9921  request.url = GURL("https://www.google.com/");
9922
9923  // Since we have proxy, should try to establish tunnel.
9924  MockWrite data_writes1[] = {
9925    MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
9926              "Host: www.google.com\r\n"
9927              "Proxy-Connection: keep-alive\r\n\r\n"),
9928
9929    MockWrite("GET / HTTP/1.1\r\n"
9930              "Host: www.google.com\r\n"
9931              "Connection: keep-alive\r\n\r\n"),
9932  };
9933
9934  MockRead data_reads1[] = {
9935    MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
9936    MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
9937    MockRead(ASYNC, 0, 0),  // EOF
9938  };
9939
9940  StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
9941                                 data_writes1, arraysize(data_writes1));
9942  session_deps_.socket_factory->AddSocketDataProvider(&data1);
9943  SSLSocketDataProvider ssl(ASYNC, OK);
9944  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9945
9946  TestCompletionCallback callback1;
9947
9948  scoped_ptr<HttpTransaction> trans(
9949      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9950
9951  int rv = trans->Start(&request, callback1.callback(), log.bound());
9952  EXPECT_EQ(ERR_IO_PENDING, rv);
9953
9954  rv = callback1.WaitForResult();
9955  EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
9956  net::CapturingNetLog::CapturedEntryList entries;
9957  log.GetEntries(&entries);
9958  size_t pos = ExpectLogContainsSomewhere(
9959      entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
9960      NetLog::PHASE_NONE);
9961  ExpectLogContainsSomewhere(
9962      entries, pos,
9963      NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
9964      NetLog::PHASE_NONE);
9965}
9966
9967// Test for crbug.com/55424.
9968TEST_P(HttpNetworkTransactionTest, PreconnectWithExistingSpdySession) {
9969  scoped_ptr<SpdyFrame> req(
9970      spdy_util_.ConstructSpdyGet("https://www.google.com", false, 1, LOWEST));
9971  MockWrite spdy_writes[] = { CreateMockWrite(*req) };
9972
9973  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
9974  scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
9975  MockRead spdy_reads[] = {
9976    CreateMockRead(*resp),
9977    CreateMockRead(*data),
9978    MockRead(ASYNC, 0, 0),
9979  };
9980
9981  DelayedSocketData spdy_data(
9982      1,  // wait for one write to finish before reading.
9983      spdy_reads, arraysize(spdy_reads),
9984      spdy_writes, arraysize(spdy_writes));
9985  session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
9986
9987  SSLSocketDataProvider ssl(ASYNC, OK);
9988  ssl.SetNextProto(GetParam());
9989  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9990
9991  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9992
9993  // Set up an initial SpdySession in the pool to reuse.
9994  HostPortPair host_port_pair("www.google.com", 443);
9995  SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
9996                     kPrivacyModeDisabled);
9997  base::WeakPtr<SpdySession> spdy_session =
9998      CreateInsecureSpdySession(session, key, BoundNetLog());
9999
10000  HttpRequestInfo request;
10001  request.method = "GET";
10002  request.url = GURL("https://www.google.com/");
10003  request.load_flags = 0;
10004
10005  // This is the important line that marks this as a preconnect.
10006  request.motivation = HttpRequestInfo::PRECONNECT_MOTIVATED;
10007
10008  scoped_ptr<HttpTransaction> trans(
10009      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10010
10011  TestCompletionCallback callback;
10012  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
10013  EXPECT_EQ(ERR_IO_PENDING, rv);
10014  EXPECT_EQ(OK, callback.WaitForResult());
10015}
10016
10017// Given a net error, cause that error to be returned from the first Write()
10018// call and verify that the HttpTransaction fails with that error.
10019void HttpNetworkTransactionTest::CheckErrorIsPassedBack(
10020    int error, IoMode mode) {
10021  net::HttpRequestInfo request_info;
10022  request_info.url = GURL("https://www.example.com/");
10023  request_info.method = "GET";
10024  request_info.load_flags = net::LOAD_NORMAL;
10025
10026  SSLSocketDataProvider ssl_data(mode, OK);
10027  net::MockWrite data_writes[] = {
10028    net::MockWrite(mode, error),
10029  };
10030  net::StaticSocketDataProvider data(NULL, 0,
10031                                     data_writes, arraysize(data_writes));
10032  session_deps_.socket_factory->AddSocketDataProvider(&data);
10033  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data);
10034
10035  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10036  scoped_ptr<HttpTransaction> trans(
10037      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10038
10039  TestCompletionCallback callback;
10040  int rv = trans->Start(&request_info, callback.callback(), net::BoundNetLog());
10041  if (rv == net::ERR_IO_PENDING)
10042    rv = callback.WaitForResult();
10043  ASSERT_EQ(error, rv);
10044}
10045
10046TEST_P(HttpNetworkTransactionTest, SSLWriteCertError) {
10047  // Just check a grab bag of cert errors.
10048  static const int kErrors[] = {
10049    ERR_CERT_COMMON_NAME_INVALID,
10050    ERR_CERT_AUTHORITY_INVALID,
10051    ERR_CERT_DATE_INVALID,
10052  };
10053  for (size_t i = 0; i < arraysize(kErrors); i++) {
10054    CheckErrorIsPassedBack(kErrors[i], ASYNC);
10055    CheckErrorIsPassedBack(kErrors[i], SYNCHRONOUS);
10056  }
10057}
10058
10059// Ensure that a client certificate is removed from the SSL client auth
10060// cache when:
10061//  1) No proxy is involved.
10062//  2) TLS False Start is disabled.
10063//  3) The initial TLS handshake requests a client certificate.
10064//  4) The client supplies an invalid/unacceptable certificate.
10065TEST_P(HttpNetworkTransactionTest,
10066       ClientAuthCertCache_Direct_NoFalseStart) {
10067  net::HttpRequestInfo request_info;
10068  request_info.url = GURL("https://www.example.com/");
10069  request_info.method = "GET";
10070  request_info.load_flags = net::LOAD_NORMAL;
10071
10072  scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
10073  cert_request->host_and_port = "www.example.com:443";
10074
10075  // [ssl_]data1 contains the data for the first SSL handshake. When a
10076  // CertificateRequest is received for the first time, the handshake will
10077  // be aborted to allow the caller to provide a certificate.
10078  SSLSocketDataProvider ssl_data1(ASYNC, net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
10079  ssl_data1.cert_request_info = cert_request.get();
10080  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
10081  net::StaticSocketDataProvider data1(NULL, 0, NULL, 0);
10082  session_deps_.socket_factory->AddSocketDataProvider(&data1);
10083
10084  // [ssl_]data2 contains the data for the second SSL handshake. When TLS
10085  // False Start is not being used, the result of the SSL handshake will be
10086  // returned as part of the SSLClientSocket::Connect() call. This test
10087  // matches the result of a server sending a handshake_failure alert,
10088  // rather than a Finished message, because it requires a client
10089  // certificate and none was supplied.
10090  SSLSocketDataProvider ssl_data2(ASYNC, net::ERR_SSL_PROTOCOL_ERROR);
10091  ssl_data2.cert_request_info = cert_request.get();
10092  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
10093  net::StaticSocketDataProvider data2(NULL, 0, NULL, 0);
10094  session_deps_.socket_factory->AddSocketDataProvider(&data2);
10095
10096  // [ssl_]data3 contains the data for the third SSL handshake. When a
10097  // connection to a server fails during an SSL handshake,
10098  // HttpNetworkTransaction will attempt to fallback to TLSv1 if the previous
10099  // connection was attempted with TLSv1.1. This is transparent to the caller
10100  // of the HttpNetworkTransaction. Because this test failure is due to
10101  // requiring a client certificate, this fallback handshake should also
10102  // fail.
10103  SSLSocketDataProvider ssl_data3(ASYNC, net::ERR_SSL_PROTOCOL_ERROR);
10104  ssl_data3.cert_request_info = cert_request.get();
10105  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
10106  net::StaticSocketDataProvider data3(NULL, 0, NULL, 0);
10107  session_deps_.socket_factory->AddSocketDataProvider(&data3);
10108
10109  // [ssl_]data4 contains the data for the fourth SSL handshake. When a
10110  // connection to a server fails during an SSL handshake,
10111  // HttpNetworkTransaction will attempt to fallback to SSLv3 if the previous
10112  // connection was attempted with TLSv1. This is transparent to the caller
10113  // of the HttpNetworkTransaction. Because this test failure is due to
10114  // requiring a client certificate, this fallback handshake should also
10115  // fail.
10116  SSLSocketDataProvider ssl_data4(ASYNC, net::ERR_SSL_PROTOCOL_ERROR);
10117  ssl_data4.cert_request_info = cert_request.get();
10118  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data4);
10119  net::StaticSocketDataProvider data4(NULL, 0, NULL, 0);
10120  session_deps_.socket_factory->AddSocketDataProvider(&data4);
10121
10122  // Need one more if TLSv1.2 is enabled.
10123  SSLSocketDataProvider ssl_data5(ASYNC, net::ERR_SSL_PROTOCOL_ERROR);
10124  ssl_data5.cert_request_info = cert_request.get();
10125  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data5);
10126  net::StaticSocketDataProvider data5(NULL, 0, NULL, 0);
10127  session_deps_.socket_factory->AddSocketDataProvider(&data5);
10128
10129  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10130  scoped_ptr<HttpTransaction> trans(
10131      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10132
10133  // Begin the SSL handshake with the peer. This consumes ssl_data1.
10134  TestCompletionCallback callback;
10135  int rv = trans->Start(&request_info, callback.callback(), net::BoundNetLog());
10136  ASSERT_EQ(net::ERR_IO_PENDING, rv);
10137
10138  // Complete the SSL handshake, which should abort due to requiring a
10139  // client certificate.
10140  rv = callback.WaitForResult();
10141  ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
10142
10143  // Indicate that no certificate should be supplied. From the perspective
10144  // of SSLClientCertCache, NULL is just as meaningful as a real
10145  // certificate, so this is the same as supply a
10146  // legitimate-but-unacceptable certificate.
10147  rv = trans->RestartWithCertificate(NULL, callback.callback());
10148  ASSERT_EQ(net::ERR_IO_PENDING, rv);
10149
10150  // Ensure the certificate was added to the client auth cache before
10151  // allowing the connection to continue restarting.
10152  scoped_refptr<X509Certificate> client_cert;
10153  ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
10154                                                       &client_cert));
10155  ASSERT_EQ(NULL, client_cert.get());
10156
10157  // Restart the handshake. This will consume ssl_data2, which fails, and
10158  // then consume ssl_data3 and ssl_data4, both of which should also fail.
10159  // The result code is checked against what ssl_data4 should return.
10160  rv = callback.WaitForResult();
10161  ASSERT_EQ(net::ERR_SSL_PROTOCOL_ERROR, rv);
10162
10163  // Ensure that the client certificate is removed from the cache on a
10164  // handshake failure.
10165  ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
10166                                                        &client_cert));
10167}
10168
10169// Ensure that a client certificate is removed from the SSL client auth
10170// cache when:
10171//  1) No proxy is involved.
10172//  2) TLS False Start is enabled.
10173//  3) The initial TLS handshake requests a client certificate.
10174//  4) The client supplies an invalid/unacceptable certificate.
10175TEST_P(HttpNetworkTransactionTest,
10176       ClientAuthCertCache_Direct_FalseStart) {
10177  net::HttpRequestInfo request_info;
10178  request_info.url = GURL("https://www.example.com/");
10179  request_info.method = "GET";
10180  request_info.load_flags = net::LOAD_NORMAL;
10181
10182  scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
10183  cert_request->host_and_port = "www.example.com:443";
10184
10185  // When TLS False Start is used, SSLClientSocket::Connect() calls will
10186  // return successfully after reading up to the peer's Certificate message.
10187  // This is to allow the caller to call SSLClientSocket::Write(), which can
10188  // enqueue application data to be sent in the same packet as the
10189  // ChangeCipherSpec and Finished messages.
10190  // The actual handshake will be finished when SSLClientSocket::Read() is
10191  // called, which expects to process the peer's ChangeCipherSpec and
10192  // Finished messages. If there was an error negotiating with the peer,
10193  // such as due to the peer requiring a client certificate when none was
10194  // supplied, the alert sent by the peer won't be processed until Read() is
10195  // called.
10196
10197  // Like the non-False Start case, when a client certificate is requested by
10198  // the peer, the handshake is aborted during the Connect() call.
10199  // [ssl_]data1 represents the initial SSL handshake with the peer.
10200  SSLSocketDataProvider ssl_data1(ASYNC, net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
10201  ssl_data1.cert_request_info = cert_request.get();
10202  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
10203  net::StaticSocketDataProvider data1(NULL, 0, NULL, 0);
10204  session_deps_.socket_factory->AddSocketDataProvider(&data1);
10205
10206  // When a client certificate is supplied, Connect() will not be aborted
10207  // when the peer requests the certificate. Instead, the handshake will
10208  // artificially succeed, allowing the caller to write the HTTP request to
10209  // the socket. The handshake messages are not processed until Read() is
10210  // called, which then detects that the handshake was aborted, due to the
10211  // peer sending a handshake_failure because it requires a client
10212  // certificate.
10213  SSLSocketDataProvider ssl_data2(ASYNC, net::OK);
10214  ssl_data2.cert_request_info = cert_request.get();
10215  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
10216  net::MockRead data2_reads[] = {
10217    net::MockRead(ASYNC /* async */, net::ERR_SSL_PROTOCOL_ERROR),
10218  };
10219  net::StaticSocketDataProvider data2(
10220      data2_reads, arraysize(data2_reads), NULL, 0);
10221  session_deps_.socket_factory->AddSocketDataProvider(&data2);
10222
10223  // As described in ClientAuthCertCache_Direct_NoFalseStart, [ssl_]data3 is
10224  // the data for the SSL handshake once the TLSv1.1 connection falls back to
10225  // TLSv1. It has the same behaviour as [ssl_]data2.
10226  SSLSocketDataProvider ssl_data3(ASYNC, net::OK);
10227  ssl_data3.cert_request_info = cert_request.get();
10228  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
10229  net::StaticSocketDataProvider data3(
10230      data2_reads, arraysize(data2_reads), NULL, 0);
10231  session_deps_.socket_factory->AddSocketDataProvider(&data3);
10232
10233  // [ssl_]data4 is the data for the SSL handshake once the TLSv1 connection
10234  // falls back to SSLv3. It has the same behaviour as [ssl_]data2.
10235  SSLSocketDataProvider ssl_data4(ASYNC, net::OK);
10236  ssl_data4.cert_request_info = cert_request.get();
10237  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data4);
10238  net::StaticSocketDataProvider data4(
10239      data2_reads, arraysize(data2_reads), NULL, 0);
10240  session_deps_.socket_factory->AddSocketDataProvider(&data4);
10241
10242  // Need one more if TLSv1.2 is enabled.
10243  SSLSocketDataProvider ssl_data5(ASYNC, net::OK);
10244  ssl_data5.cert_request_info = cert_request.get();
10245  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data5);
10246  net::StaticSocketDataProvider data5(
10247      data2_reads, arraysize(data2_reads), NULL, 0);
10248  session_deps_.socket_factory->AddSocketDataProvider(&data5);
10249
10250  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10251  scoped_ptr<HttpTransaction> trans(
10252      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10253
10254  // Begin the initial SSL handshake.
10255  TestCompletionCallback callback;
10256  int rv = trans->Start(&request_info, callback.callback(), net::BoundNetLog());
10257  ASSERT_EQ(net::ERR_IO_PENDING, rv);
10258
10259  // Complete the SSL handshake, which should abort due to requiring a
10260  // client certificate.
10261  rv = callback.WaitForResult();
10262  ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
10263
10264  // Indicate that no certificate should be supplied. From the perspective
10265  // of SSLClientCertCache, NULL is just as meaningful as a real
10266  // certificate, so this is the same as supply a
10267  // legitimate-but-unacceptable certificate.
10268  rv = trans->RestartWithCertificate(NULL, callback.callback());
10269  ASSERT_EQ(net::ERR_IO_PENDING, rv);
10270
10271  // Ensure the certificate was added to the client auth cache before
10272  // allowing the connection to continue restarting.
10273  scoped_refptr<X509Certificate> client_cert;
10274  ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
10275                                                       &client_cert));
10276  ASSERT_EQ(NULL, client_cert.get());
10277
10278  // Restart the handshake. This will consume ssl_data2, which fails, and
10279  // then consume ssl_data3 and ssl_data4, both of which should also fail.
10280  // The result code is checked against what ssl_data4 should return.
10281  rv = callback.WaitForResult();
10282  ASSERT_EQ(net::ERR_SSL_PROTOCOL_ERROR, rv);
10283
10284  // Ensure that the client certificate is removed from the cache on a
10285  // handshake failure.
10286  ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
10287                                                        &client_cert));
10288}
10289
10290// Ensure that a client certificate is removed from the SSL client auth
10291// cache when:
10292//  1) An HTTPS proxy is involved.
10293//  3) The HTTPS proxy requests a client certificate.
10294//  4) The client supplies an invalid/unacceptable certificate for the
10295//     proxy.
10296// The test is repeated twice, first for connecting to an HTTPS endpoint,
10297// then for connecting to an HTTP endpoint.
10298TEST_P(HttpNetworkTransactionTest, ClientAuthCertCache_Proxy_Fail) {
10299  session_deps_.proxy_service.reset(
10300      ProxyService::CreateFixed("https://proxy:70"));
10301  CapturingBoundNetLog log;
10302  session_deps_.net_log = log.bound().net_log();
10303
10304  scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
10305  cert_request->host_and_port = "proxy:70";
10306
10307  // See ClientAuthCertCache_Direct_NoFalseStart for the explanation of
10308  // [ssl_]data[1-3]. Rather than represending the endpoint
10309  // (www.example.com:443), they represent failures with the HTTPS proxy
10310  // (proxy:70).
10311  SSLSocketDataProvider ssl_data1(ASYNC, net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
10312  ssl_data1.cert_request_info = cert_request.get();
10313  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
10314  net::StaticSocketDataProvider data1(NULL, 0, NULL, 0);
10315  session_deps_.socket_factory->AddSocketDataProvider(&data1);
10316
10317  SSLSocketDataProvider ssl_data2(ASYNC, net::ERR_SSL_PROTOCOL_ERROR);
10318  ssl_data2.cert_request_info = cert_request.get();
10319  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
10320  net::StaticSocketDataProvider data2(NULL, 0, NULL, 0);
10321  session_deps_.socket_factory->AddSocketDataProvider(&data2);
10322
10323  // TODO(wtc): find out why this unit test doesn't need [ssl_]data3.
10324#if 0
10325  SSLSocketDataProvider ssl_data3(ASYNC, net::ERR_SSL_PROTOCOL_ERROR);
10326  ssl_data3.cert_request_info = cert_request.get();
10327  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
10328  net::StaticSocketDataProvider data3(NULL, 0, NULL, 0);
10329  session_deps_.socket_factory->AddSocketDataProvider(&data3);
10330#endif
10331
10332  net::HttpRequestInfo requests[2];
10333  requests[0].url = GURL("https://www.example.com/");
10334  requests[0].method = "GET";
10335  requests[0].load_flags = net::LOAD_NORMAL;
10336
10337  requests[1].url = GURL("http://www.example.com/");
10338  requests[1].method = "GET";
10339  requests[1].load_flags = net::LOAD_NORMAL;
10340
10341  for (size_t i = 0; i < arraysize(requests); ++i) {
10342    session_deps_.socket_factory->ResetNextMockIndexes();
10343    scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10344    scoped_ptr<HttpNetworkTransaction> trans(
10345        new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10346
10347    // Begin the SSL handshake with the proxy.
10348    TestCompletionCallback callback;
10349    int rv = trans->Start(
10350        &requests[i], callback.callback(), net::BoundNetLog());
10351    ASSERT_EQ(net::ERR_IO_PENDING, rv);
10352
10353    // Complete the SSL handshake, which should abort due to requiring a
10354    // client certificate.
10355    rv = callback.WaitForResult();
10356    ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
10357
10358    // Indicate that no certificate should be supplied. From the perspective
10359    // of SSLClientCertCache, NULL is just as meaningful as a real
10360    // certificate, so this is the same as supply a
10361    // legitimate-but-unacceptable certificate.
10362    rv = trans->RestartWithCertificate(NULL, callback.callback());
10363    ASSERT_EQ(net::ERR_IO_PENDING, rv);
10364
10365    // Ensure the certificate was added to the client auth cache before
10366    // allowing the connection to continue restarting.
10367    scoped_refptr<X509Certificate> client_cert;
10368    ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup("proxy:70",
10369                                                         &client_cert));
10370    ASSERT_EQ(NULL, client_cert.get());
10371    // Ensure the certificate was NOT cached for the endpoint. This only
10372    // applies to HTTPS requests, but is fine to check for HTTP requests.
10373    ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
10374                                                          &client_cert));
10375
10376    // Restart the handshake. This will consume ssl_data2, which fails, and
10377    // then consume ssl_data3, which should also fail. The result code is
10378    // checked against what ssl_data3 should return.
10379    rv = callback.WaitForResult();
10380    ASSERT_EQ(net::ERR_PROXY_CONNECTION_FAILED, rv);
10381
10382    // Now that the new handshake has failed, ensure that the client
10383    // certificate was removed from the client auth cache.
10384    ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("proxy:70",
10385                                                          &client_cert));
10386    ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
10387                                                          &client_cert));
10388  }
10389}
10390
10391// Unlike TEST/TEST_F, which are macros that expand to further macros,
10392// TEST_P is a macro that expands directly to code that stringizes the
10393// arguments. As a result, macros passed as parameters (such as prefix
10394// or test_case_name) will not be expanded by the preprocessor. To
10395// work around this, indirect the macro for TEST_P, so that the
10396// pre-processor will expand macros such as MAYBE_test_name before
10397// instantiating the test.
10398#define WRAPPED_TEST_P(test_case_name, test_name) \
10399  TEST_P(test_case_name, test_name)
10400
10401// Times out on Win7 dbg(2) bot. http://crbug.com/124776
10402#if defined(OS_WIN)
10403#define MAYBE_UseIPConnectionPooling DISABLED_UseIPConnectionPooling
10404#else
10405#define MAYBE_UseIPConnectionPooling UseIPConnectionPooling
10406#endif
10407WRAPPED_TEST_P(HttpNetworkTransactionTest, MAYBE_UseIPConnectionPooling) {
10408  HttpStreamFactory::set_use_alternate_protocols(true);
10409  HttpStreamFactory::SetNextProtos(SpdyNextProtos());
10410
10411  // Set up a special HttpNetworkSession with a MockCachingHostResolver.
10412  session_deps_.host_resolver.reset(new MockCachingHostResolver());
10413  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10414  SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
10415  pool_peer.DisableDomainAuthenticationVerification();
10416
10417  SSLSocketDataProvider ssl(ASYNC, OK);
10418  ssl.SetNextProto(GetParam());
10419  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10420
10421  scoped_ptr<SpdyFrame> host1_req(
10422      spdy_util_.ConstructSpdyGet("https://www.google.com", false, 1, LOWEST));
10423  scoped_ptr<SpdyFrame> host2_req(
10424      spdy_util_.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST));
10425  MockWrite spdy_writes[] = {
10426    CreateMockWrite(*host1_req, 1),
10427    CreateMockWrite(*host2_req, 4),
10428  };
10429  scoped_ptr<SpdyFrame> host1_resp(
10430      spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
10431  scoped_ptr<SpdyFrame> host1_resp_body(
10432      spdy_util_.ConstructSpdyBodyFrame(1, true));
10433  scoped_ptr<SpdyFrame> host2_resp(
10434      spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
10435  scoped_ptr<SpdyFrame> host2_resp_body(
10436      spdy_util_.ConstructSpdyBodyFrame(3, true));
10437  MockRead spdy_reads[] = {
10438    CreateMockRead(*host1_resp, 2),
10439    CreateMockRead(*host1_resp_body, 3),
10440    CreateMockRead(*host2_resp, 5),
10441    CreateMockRead(*host2_resp_body, 6),
10442    MockRead(ASYNC, 0, 7),
10443  };
10444
10445  IPAddressNumber ip;
10446  ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip));
10447  IPEndPoint peer_addr = IPEndPoint(ip, 443);
10448  MockConnect connect(ASYNC, OK, peer_addr);
10449  OrderedSocketData spdy_data(
10450      connect,
10451      spdy_reads, arraysize(spdy_reads),
10452      spdy_writes, arraysize(spdy_writes));
10453  session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
10454
10455  TestCompletionCallback callback;
10456  HttpRequestInfo request1;
10457  request1.method = "GET";
10458  request1.url = GURL("https://www.google.com/");
10459  request1.load_flags = 0;
10460  HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
10461
10462  int rv = trans1.Start(&request1, callback.callback(), BoundNetLog());
10463  EXPECT_EQ(ERR_IO_PENDING, rv);
10464  EXPECT_EQ(OK, callback.WaitForResult());
10465
10466  const HttpResponseInfo* response = trans1.GetResponseInfo();
10467  ASSERT_TRUE(response != NULL);
10468  ASSERT_TRUE(response->headers.get() != NULL);
10469  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10470
10471  std::string response_data;
10472  ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
10473  EXPECT_EQ("hello!", response_data);
10474
10475  // Preload www.gmail.com into HostCache.
10476  HostPortPair host_port("www.gmail.com", 443);
10477  HostResolver::RequestInfo resolve_info(host_port);
10478  AddressList ignored;
10479  rv = session_deps_.host_resolver->Resolve(resolve_info, &ignored,
10480                                           callback.callback(), NULL,
10481                                           BoundNetLog());
10482  EXPECT_EQ(ERR_IO_PENDING, rv);
10483  rv = callback.WaitForResult();
10484  EXPECT_EQ(OK, rv);
10485
10486  HttpRequestInfo request2;
10487  request2.method = "GET";
10488  request2.url = GURL("https://www.gmail.com/");
10489  request2.load_flags = 0;
10490  HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
10491
10492  rv = trans2.Start(&request2, callback.callback(), BoundNetLog());
10493  EXPECT_EQ(ERR_IO_PENDING, rv);
10494  EXPECT_EQ(OK, callback.WaitForResult());
10495
10496  response = trans2.GetResponseInfo();
10497  ASSERT_TRUE(response != NULL);
10498  ASSERT_TRUE(response->headers.get() != NULL);
10499  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10500  EXPECT_TRUE(response->was_fetched_via_spdy);
10501  EXPECT_TRUE(response->was_npn_negotiated);
10502  ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
10503  EXPECT_EQ("hello!", response_data);
10504}
10505#undef MAYBE_UseIPConnectionPooling
10506
10507TEST_P(HttpNetworkTransactionTest, UseIPConnectionPoolingAfterResolution) {
10508  HttpStreamFactory::set_use_alternate_protocols(true);
10509  HttpStreamFactory::SetNextProtos(SpdyNextProtos());
10510
10511  // Set up a special HttpNetworkSession with a MockCachingHostResolver.
10512  session_deps_.host_resolver.reset(new MockCachingHostResolver());
10513  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10514  SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
10515  pool_peer.DisableDomainAuthenticationVerification();
10516
10517  SSLSocketDataProvider ssl(ASYNC, OK);
10518  ssl.SetNextProto(GetParam());
10519  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10520
10521  scoped_ptr<SpdyFrame> host1_req(
10522      spdy_util_.ConstructSpdyGet("https://www.google.com", false, 1, LOWEST));
10523  scoped_ptr<SpdyFrame> host2_req(
10524      spdy_util_.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST));
10525  MockWrite spdy_writes[] = {
10526    CreateMockWrite(*host1_req, 1),
10527    CreateMockWrite(*host2_req, 4),
10528  };
10529  scoped_ptr<SpdyFrame> host1_resp(
10530      spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
10531  scoped_ptr<SpdyFrame> host1_resp_body(
10532      spdy_util_.ConstructSpdyBodyFrame(1, true));
10533  scoped_ptr<SpdyFrame> host2_resp(
10534      spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
10535  scoped_ptr<SpdyFrame> host2_resp_body(
10536      spdy_util_.ConstructSpdyBodyFrame(3, true));
10537  MockRead spdy_reads[] = {
10538    CreateMockRead(*host1_resp, 2),
10539    CreateMockRead(*host1_resp_body, 3),
10540    CreateMockRead(*host2_resp, 5),
10541    CreateMockRead(*host2_resp_body, 6),
10542    MockRead(ASYNC, 0, 7),
10543  };
10544
10545  IPAddressNumber ip;
10546  ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip));
10547  IPEndPoint peer_addr = IPEndPoint(ip, 443);
10548  MockConnect connect(ASYNC, OK, peer_addr);
10549  OrderedSocketData spdy_data(
10550      connect,
10551      spdy_reads, arraysize(spdy_reads),
10552      spdy_writes, arraysize(spdy_writes));
10553  session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
10554
10555  TestCompletionCallback callback;
10556  HttpRequestInfo request1;
10557  request1.method = "GET";
10558  request1.url = GURL("https://www.google.com/");
10559  request1.load_flags = 0;
10560  HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
10561
10562  int rv = trans1.Start(&request1, callback.callback(), BoundNetLog());
10563  EXPECT_EQ(ERR_IO_PENDING, rv);
10564  EXPECT_EQ(OK, callback.WaitForResult());
10565
10566  const HttpResponseInfo* response = trans1.GetResponseInfo();
10567  ASSERT_TRUE(response != NULL);
10568  ASSERT_TRUE(response->headers.get() != NULL);
10569  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10570
10571  std::string response_data;
10572  ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
10573  EXPECT_EQ("hello!", response_data);
10574
10575  HttpRequestInfo request2;
10576  request2.method = "GET";
10577  request2.url = GURL("https://www.gmail.com/");
10578  request2.load_flags = 0;
10579  HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
10580
10581  rv = trans2.Start(&request2, callback.callback(), BoundNetLog());
10582  EXPECT_EQ(ERR_IO_PENDING, rv);
10583  EXPECT_EQ(OK, callback.WaitForResult());
10584
10585  response = trans2.GetResponseInfo();
10586  ASSERT_TRUE(response != NULL);
10587  ASSERT_TRUE(response->headers.get() != NULL);
10588  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10589  EXPECT_TRUE(response->was_fetched_via_spdy);
10590  EXPECT_TRUE(response->was_npn_negotiated);
10591  ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
10592  EXPECT_EQ("hello!", response_data);
10593}
10594
10595class OneTimeCachingHostResolver : public net::HostResolver {
10596 public:
10597  explicit OneTimeCachingHostResolver(const HostPortPair& host_port)
10598      : host_port_(host_port) {}
10599  virtual ~OneTimeCachingHostResolver() {}
10600
10601  RuleBasedHostResolverProc* rules() { return host_resolver_.rules(); }
10602
10603  // HostResolver methods:
10604  virtual int Resolve(const RequestInfo& info,
10605                      AddressList* addresses,
10606                      const CompletionCallback& callback,
10607                      RequestHandle* out_req,
10608                      const BoundNetLog& net_log) OVERRIDE {
10609    return host_resolver_.Resolve(
10610        info, addresses, callback, out_req, net_log);
10611  }
10612
10613  virtual int ResolveFromCache(const RequestInfo& info,
10614                               AddressList* addresses,
10615                               const BoundNetLog& net_log) OVERRIDE {
10616    int rv = host_resolver_.ResolveFromCache(info, addresses, net_log);
10617    if (rv == OK && info.host_port_pair().Equals(host_port_))
10618      host_resolver_.GetHostCache()->clear();
10619    return rv;
10620  }
10621
10622  virtual void CancelRequest(RequestHandle req) OVERRIDE {
10623    host_resolver_.CancelRequest(req);
10624  }
10625
10626  MockCachingHostResolver* GetMockHostResolver() {
10627    return &host_resolver_;
10628  }
10629
10630 private:
10631  MockCachingHostResolver host_resolver_;
10632  const HostPortPair host_port_;
10633};
10634
10635// Times out on Win7 dbg(2) bot. http://crbug.com/124776
10636#if defined(OS_WIN)
10637#define MAYBE_UseIPConnectionPoolingWithHostCacheExpiration \
10638    DISABLED_UseIPConnectionPoolingWithHostCacheExpiration
10639#else
10640#define MAYBE_UseIPConnectionPoolingWithHostCacheExpiration \
10641    UseIPConnectionPoolingWithHostCacheExpiration
10642#endif
10643WRAPPED_TEST_P(HttpNetworkTransactionTest,
10644               MAYBE_UseIPConnectionPoolingWithHostCacheExpiration) {
10645// Times out on Win7 dbg(2) bot. http://crbug.com/124776 . (MAYBE_
10646// prefix doesn't work with parametrized tests).
10647#if defined(OS_WIN)
10648  return;
10649#endif
10650
10651  HttpStreamFactory::set_use_alternate_protocols(true);
10652  HttpStreamFactory::SetNextProtos(SpdyNextProtos());
10653
10654  // Set up a special HttpNetworkSession with a OneTimeCachingHostResolver.
10655  OneTimeCachingHostResolver host_resolver(HostPortPair("www.gmail.com", 443));
10656  HttpNetworkSession::Params params =
10657      SpdySessionDependencies::CreateSessionParams(&session_deps_);
10658  params.host_resolver = &host_resolver;
10659  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10660  SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
10661  pool_peer.DisableDomainAuthenticationVerification();
10662
10663  SSLSocketDataProvider ssl(ASYNC, OK);
10664  ssl.SetNextProto(GetParam());
10665  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10666
10667  scoped_ptr<SpdyFrame> host1_req(
10668      spdy_util_.ConstructSpdyGet("https://www.google.com", false, 1, LOWEST));
10669  scoped_ptr<SpdyFrame> host2_req(
10670      spdy_util_.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST));
10671  MockWrite spdy_writes[] = {
10672    CreateMockWrite(*host1_req, 1),
10673    CreateMockWrite(*host2_req, 4),
10674  };
10675  scoped_ptr<SpdyFrame> host1_resp(
10676      spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
10677  scoped_ptr<SpdyFrame> host1_resp_body(
10678      spdy_util_.ConstructSpdyBodyFrame(1, true));
10679  scoped_ptr<SpdyFrame> host2_resp(
10680      spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
10681  scoped_ptr<SpdyFrame> host2_resp_body(
10682      spdy_util_.ConstructSpdyBodyFrame(3, true));
10683  MockRead spdy_reads[] = {
10684    CreateMockRead(*host1_resp, 2),
10685    CreateMockRead(*host1_resp_body, 3),
10686    CreateMockRead(*host2_resp, 5),
10687    CreateMockRead(*host2_resp_body, 6),
10688    MockRead(ASYNC, 0, 7),
10689  };
10690
10691  IPAddressNumber ip;
10692  ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip));
10693  IPEndPoint peer_addr = IPEndPoint(ip, 443);
10694  MockConnect connect(ASYNC, OK, peer_addr);
10695  OrderedSocketData spdy_data(
10696      connect,
10697      spdy_reads, arraysize(spdy_reads),
10698      spdy_writes, arraysize(spdy_writes));
10699  session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
10700
10701  TestCompletionCallback callback;
10702  HttpRequestInfo request1;
10703  request1.method = "GET";
10704  request1.url = GURL("https://www.google.com/");
10705  request1.load_flags = 0;
10706  HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
10707
10708  int rv = trans1.Start(&request1, callback.callback(), BoundNetLog());
10709  EXPECT_EQ(ERR_IO_PENDING, rv);
10710  EXPECT_EQ(OK, callback.WaitForResult());
10711
10712  const HttpResponseInfo* response = trans1.GetResponseInfo();
10713  ASSERT_TRUE(response != NULL);
10714  ASSERT_TRUE(response->headers.get() != NULL);
10715  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10716
10717  std::string response_data;
10718  ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
10719  EXPECT_EQ("hello!", response_data);
10720
10721  // Preload cache entries into HostCache.
10722  HostResolver::RequestInfo resolve_info(HostPortPair("www.gmail.com", 443));
10723  AddressList ignored;
10724  rv = host_resolver.Resolve(resolve_info, &ignored, callback.callback(),
10725                             NULL, BoundNetLog());
10726  EXPECT_EQ(ERR_IO_PENDING, rv);
10727  rv = callback.WaitForResult();
10728  EXPECT_EQ(OK, rv);
10729
10730  HttpRequestInfo request2;
10731  request2.method = "GET";
10732  request2.url = GURL("https://www.gmail.com/");
10733  request2.load_flags = 0;
10734  HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
10735
10736  rv = trans2.Start(&request2, callback.callback(), BoundNetLog());
10737  EXPECT_EQ(ERR_IO_PENDING, rv);
10738  EXPECT_EQ(OK, callback.WaitForResult());
10739
10740  response = trans2.GetResponseInfo();
10741  ASSERT_TRUE(response != NULL);
10742  ASSERT_TRUE(response->headers.get() != NULL);
10743  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10744  EXPECT_TRUE(response->was_fetched_via_spdy);
10745  EXPECT_TRUE(response->was_npn_negotiated);
10746  ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
10747  EXPECT_EQ("hello!", response_data);
10748}
10749#undef MAYBE_UseIPConnectionPoolingWithHostCacheExpiration
10750
10751TEST_P(HttpNetworkTransactionTest, ReadPipelineEvictionFallback) {
10752  MockRead data_reads1[] = {
10753    MockRead(SYNCHRONOUS, ERR_PIPELINE_EVICTION),
10754  };
10755  MockRead data_reads2[] = {
10756    MockRead("HTTP/1.0 200 OK\r\n\r\n"),
10757    MockRead("hello world"),
10758    MockRead(SYNCHRONOUS, OK),
10759  };
10760  StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), NULL, 0);
10761  StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), NULL, 0);
10762  StaticSocketDataProvider* data[] = { &data1, &data2 };
10763
10764  SimpleGetHelperResult out = SimpleGetHelperForData(data, arraysize(data));
10765
10766  EXPECT_EQ(OK, out.rv);
10767  EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
10768  EXPECT_EQ("hello world", out.response_data);
10769}
10770
10771TEST_P(HttpNetworkTransactionTest, SendPipelineEvictionFallback) {
10772  MockWrite data_writes1[] = {
10773    MockWrite(SYNCHRONOUS, ERR_PIPELINE_EVICTION),
10774  };
10775  MockWrite data_writes2[] = {
10776    MockWrite("GET / HTTP/1.1\r\n"
10777              "Host: www.google.com\r\n"
10778              "Connection: keep-alive\r\n\r\n"),
10779  };
10780  MockRead data_reads2[] = {
10781    MockRead("HTTP/1.0 200 OK\r\n\r\n"),
10782    MockRead("hello world"),
10783    MockRead(SYNCHRONOUS, OK),
10784  };
10785  StaticSocketDataProvider data1(NULL, 0,
10786                                 data_writes1, arraysize(data_writes1));
10787  StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
10788                                 data_writes2, arraysize(data_writes2));
10789  StaticSocketDataProvider* data[] = { &data1, &data2 };
10790
10791  SimpleGetHelperResult out = SimpleGetHelperForData(data, arraysize(data));
10792
10793  EXPECT_EQ(OK, out.rv);
10794  EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
10795  EXPECT_EQ("hello world", out.response_data);
10796}
10797
10798TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttp) {
10799  const std::string https_url = "https://www.google.com/";
10800  const std::string http_url = "http://www.google.com:443/";
10801
10802  // SPDY GET for HTTPS URL
10803  scoped_ptr<SpdyFrame> req1(
10804      spdy_util_.ConstructSpdyGet(https_url.c_str(), false, 1, LOWEST));
10805
10806  MockWrite writes1[] = {
10807    CreateMockWrite(*req1, 0),
10808  };
10809
10810  scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
10811  scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
10812  MockRead reads1[] = {
10813    CreateMockRead(*resp1, 1),
10814    CreateMockRead(*body1, 2),
10815    MockRead(ASYNC, ERR_IO_PENDING, 3)
10816  };
10817
10818  DelayedSocketData data1(
10819      1, reads1, arraysize(reads1),
10820      writes1, arraysize(writes1));
10821  MockConnect connect_data1(ASYNC, OK);
10822  data1.set_connect_data(connect_data1);
10823
10824  // HTTP GET for the HTTP URL
10825  MockWrite writes2[] = {
10826    MockWrite(ASYNC, 4,
10827              "GET / HTTP/1.1\r\n"
10828              "Host: www.google.com:443\r\n"
10829              "Connection: keep-alive\r\n\r\n"),
10830  };
10831
10832  MockRead reads2[] = {
10833    MockRead(ASYNC, 5, "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
10834    MockRead(ASYNC, 6, "hello"),
10835    MockRead(ASYNC, 7, OK),
10836  };
10837
10838  DelayedSocketData data2(
10839      1, reads2, arraysize(reads2),
10840      writes2, arraysize(writes2));
10841
10842  SSLSocketDataProvider ssl(ASYNC, OK);
10843  ssl.SetNextProto(GetParam());
10844  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10845  session_deps_.socket_factory->AddSocketDataProvider(&data1);
10846  session_deps_.socket_factory->AddSocketDataProvider(&data2);
10847
10848  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10849
10850  // Start the first transaction to set up the SpdySession
10851  HttpRequestInfo request1;
10852  request1.method = "GET";
10853  request1.url = GURL(https_url);
10854  request1.load_flags = 0;
10855  HttpNetworkTransaction trans1(LOWEST, session.get());
10856  TestCompletionCallback callback1;
10857  EXPECT_EQ(ERR_IO_PENDING,
10858            trans1.Start(&request1, callback1.callback(), BoundNetLog()));
10859  base::MessageLoop::current()->RunUntilIdle();
10860
10861  EXPECT_EQ(OK, callback1.WaitForResult());
10862  EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
10863
10864  // Now, start the HTTP request
10865  HttpRequestInfo request2;
10866  request2.method = "GET";
10867  request2.url = GURL(http_url);
10868  request2.load_flags = 0;
10869  HttpNetworkTransaction trans2(MEDIUM, session.get());
10870  TestCompletionCallback callback2;
10871  EXPECT_EQ(ERR_IO_PENDING,
10872            trans2.Start(&request2, callback2.callback(), BoundNetLog()));
10873  base::MessageLoop::current()->RunUntilIdle();
10874
10875  EXPECT_EQ(OK, callback2.WaitForResult());
10876  EXPECT_FALSE(trans2.GetResponseInfo()->was_fetched_via_spdy);
10877}
10878
10879TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttpOverTunnel) {
10880  const std::string https_url = "https://www.google.com/";
10881  const std::string http_url = "http://www.google.com:443/";
10882
10883  // SPDY GET for HTTPS URL (through CONNECT tunnel)
10884  scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(NULL, 0, 1));
10885  scoped_ptr<SpdyFrame> req1(
10886      spdy_util_.ConstructSpdyGet(https_url.c_str(), false, 1, LOWEST));
10887
10888  // SPDY GET for HTTP URL (through the proxy, but not the tunnel)
10889  scoped_ptr<SpdyFrame> wrapped_req1(
10890      spdy_util_.ConstructWrappedSpdyFrame(req1, 1));
10891  const char* const headers[] = {
10892    spdy_util_.GetMethodKey(), "GET",
10893    spdy_util_.GetPathKey(), spdy_util_.is_spdy2() ? http_url.c_str() : "/",
10894    spdy_util_.GetHostKey(),  "www.google.com:443",
10895    spdy_util_.GetSchemeKey(), "http",
10896    spdy_util_.GetVersionKey(), "HTTP/1.1"
10897  };
10898  scoped_ptr<SpdyFrame> req2(spdy_util_.ConstructSpdyControlFrame(
10899      NULL, 0, false, 3, MEDIUM, SYN_STREAM, CONTROL_FLAG_FIN,
10900      headers, arraysize(headers), 0));
10901
10902  MockWrite writes1[] = {
10903    CreateMockWrite(*connect, 0),
10904    CreateMockWrite(*wrapped_req1, 2),
10905    CreateMockWrite(*req2, 5),
10906  };
10907
10908  scoped_ptr<SpdyFrame> conn_resp(
10909      spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
10910  scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
10911  scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
10912  scoped_ptr<SpdyFrame> wrapped_resp1(
10913      spdy_util_.ConstructWrappedSpdyFrame(resp1, 1));
10914  scoped_ptr<SpdyFrame> wrapped_body1(
10915      spdy_util_.ConstructWrappedSpdyFrame(body1, 1));
10916  scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
10917  scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, true));
10918  MockRead reads1[] = {
10919    CreateMockRead(*conn_resp, 1),
10920    CreateMockRead(*wrapped_resp1, 3),
10921    CreateMockRead(*wrapped_body1, 4),
10922    CreateMockRead(*resp2, 6),
10923    CreateMockRead(*body2, 7),
10924    MockRead(ASYNC, ERR_IO_PENDING, 8)
10925  };
10926
10927  DeterministicSocketData data1(reads1, arraysize(reads1),
10928                                writes1, arraysize(writes1));
10929  MockConnect connect_data1(ASYNC, OK);
10930  data1.set_connect_data(connect_data1);
10931
10932  session_deps_.proxy_service.reset(
10933      ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
10934  CapturingNetLog log;
10935  session_deps_.net_log = &log;
10936  SSLSocketDataProvider ssl1(ASYNC, OK);  // to the proxy
10937  ssl1.SetNextProto(GetParam());
10938  session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl1);
10939  SSLSocketDataProvider ssl2(ASYNC, OK);  // to the server
10940  ssl2.SetNextProto(GetParam());
10941  session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2);
10942  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data1);
10943
10944  scoped_refptr<HttpNetworkSession> session(
10945      SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
10946
10947  // Start the first transaction to set up the SpdySession
10948  HttpRequestInfo request1;
10949  request1.method = "GET";
10950  request1.url = GURL(https_url);
10951  request1.load_flags = 0;
10952  HttpNetworkTransaction trans1(LOWEST, session.get());
10953  TestCompletionCallback callback1;
10954  EXPECT_EQ(ERR_IO_PENDING,
10955            trans1.Start(&request1, callback1.callback(), BoundNetLog()));
10956  base::MessageLoop::current()->RunUntilIdle();
10957  data1.RunFor(4);
10958
10959  EXPECT_EQ(OK, callback1.WaitForResult());
10960  EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
10961
10962  LoadTimingInfo load_timing_info1;
10963  EXPECT_TRUE(trans1.GetLoadTimingInfo(&load_timing_info1));
10964  TestLoadTimingNotReusedWithPac(load_timing_info1,
10965                                 CONNECT_TIMING_HAS_SSL_TIMES);
10966
10967  // Now, start the HTTP request
10968  HttpRequestInfo request2;
10969  request2.method = "GET";
10970  request2.url = GURL(http_url);
10971  request2.load_flags = 0;
10972  HttpNetworkTransaction trans2(MEDIUM, session.get());
10973  TestCompletionCallback callback2;
10974  EXPECT_EQ(ERR_IO_PENDING,
10975            trans2.Start(&request2, callback2.callback(), BoundNetLog()));
10976  base::MessageLoop::current()->RunUntilIdle();
10977  data1.RunFor(3);
10978
10979  EXPECT_EQ(OK, callback2.WaitForResult());
10980  EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
10981
10982  LoadTimingInfo load_timing_info2;
10983  EXPECT_TRUE(trans2.GetLoadTimingInfo(&load_timing_info2));
10984  // The established SPDY sessions is considered reused by the HTTP request.
10985  TestLoadTimingReusedWithPac(load_timing_info2);
10986  // HTTP requests over a SPDY session should have a different connection
10987  // socket_log_id than requests over a tunnel.
10988  EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
10989}
10990
10991TEST_P(HttpNetworkTransactionTest, UseSpdySessionForHttpWhenForced) {
10992  HttpStreamFactory::set_force_spdy_always(true);
10993  const std::string https_url = "https://www.google.com/";
10994  const std::string http_url = "http://www.google.com:443/";
10995
10996  // SPDY GET for HTTPS URL
10997  scoped_ptr<SpdyFrame> req1(
10998      spdy_util_.ConstructSpdyGet(https_url.c_str(), false, 1, LOWEST));
10999  // SPDY GET for the HTTP URL
11000  scoped_ptr<SpdyFrame> req2(
11001      spdy_util_.ConstructSpdyGet(http_url.c_str(), false, 3, MEDIUM));
11002
11003  MockWrite writes[] = {
11004    CreateMockWrite(*req1, 1),
11005    CreateMockWrite(*req2, 4),
11006  };
11007
11008  scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11009  scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
11010  scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
11011  scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, true));
11012  MockRead reads[] = {
11013    CreateMockRead(*resp1, 2),
11014    CreateMockRead(*body1, 3),
11015    CreateMockRead(*resp2, 5),
11016    CreateMockRead(*body2, 6),
11017    MockRead(ASYNC, ERR_IO_PENDING, 7)
11018  };
11019
11020  OrderedSocketData data(reads, arraysize(reads),
11021                         writes, arraysize(writes));
11022
11023  SSLSocketDataProvider ssl(ASYNC, OK);
11024  ssl.SetNextProto(GetParam());
11025  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11026  session_deps_.socket_factory->AddSocketDataProvider(&data);
11027
11028  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11029
11030  // Start the first transaction to set up the SpdySession
11031  HttpRequestInfo request1;
11032  request1.method = "GET";
11033  request1.url = GURL(https_url);
11034  request1.load_flags = 0;
11035  HttpNetworkTransaction trans1(LOWEST, session.get());
11036  TestCompletionCallback callback1;
11037  EXPECT_EQ(ERR_IO_PENDING,
11038            trans1.Start(&request1, callback1.callback(), BoundNetLog()));
11039  base::MessageLoop::current()->RunUntilIdle();
11040
11041  EXPECT_EQ(OK, callback1.WaitForResult());
11042  EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
11043
11044  // Now, start the HTTP request
11045  HttpRequestInfo request2;
11046  request2.method = "GET";
11047  request2.url = GURL(http_url);
11048  request2.load_flags = 0;
11049  HttpNetworkTransaction trans2(MEDIUM, session.get());
11050  TestCompletionCallback callback2;
11051  EXPECT_EQ(ERR_IO_PENDING,
11052            trans2.Start(&request2, callback2.callback(), BoundNetLog()));
11053  base::MessageLoop::current()->RunUntilIdle();
11054
11055  EXPECT_EQ(OK, callback2.WaitForResult());
11056  EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
11057}
11058
11059// Test that in the case where we have a SPDY session to a SPDY proxy
11060// that we do not pool other origins that resolve to the same IP when
11061// the certificate does not match the new origin.
11062// http://crbug.com/134690
11063TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionIfCertDoesNotMatch) {
11064  const std::string url1 = "http://www.google.com/";
11065  const std::string url2 = "https://mail.google.com/";
11066  const std::string ip_addr = "1.2.3.4";
11067
11068  // SPDY GET for HTTP URL (through SPDY proxy)
11069  scoped_ptr<SpdyHeaderBlock> headers(
11070      spdy_util_.ConstructGetHeaderBlockForProxy("http://www.google.com/"));
11071  scoped_ptr<SpdyFrame> req1(spdy_util_.ConstructSpdyControlFrame(
11072      headers.Pass(), false, 1, LOWEST, SYN_STREAM, CONTROL_FLAG_FIN, 0));
11073
11074  MockWrite writes1[] = {
11075    CreateMockWrite(*req1, 0),
11076  };
11077
11078  scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11079  scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
11080  MockRead reads1[] = {
11081    CreateMockRead(*resp1, 1),
11082    CreateMockRead(*body1, 2),
11083    MockRead(ASYNC, OK, 3) // EOF
11084  };
11085
11086  scoped_ptr<DeterministicSocketData> data1(
11087      new DeterministicSocketData(reads1, arraysize(reads1),
11088                                  writes1, arraysize(writes1)));
11089  IPAddressNumber ip;
11090  ASSERT_TRUE(ParseIPLiteralToNumber(ip_addr, &ip));
11091  IPEndPoint peer_addr = IPEndPoint(ip, 443);
11092  MockConnect connect_data1(ASYNC, OK, peer_addr);
11093  data1->set_connect_data(connect_data1);
11094
11095  // SPDY GET for HTTPS URL (direct)
11096  scoped_ptr<SpdyFrame> req2(
11097      spdy_util_.ConstructSpdyGet(url2.c_str(), false, 1, MEDIUM));
11098
11099  MockWrite writes2[] = {
11100    CreateMockWrite(*req2, 0),
11101  };
11102
11103  scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11104  scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
11105  MockRead reads2[] = {
11106    CreateMockRead(*resp2, 1),
11107    CreateMockRead(*body2, 2),
11108    MockRead(ASYNC, OK, 3) // EOF
11109  };
11110
11111  scoped_ptr<DeterministicSocketData> data2(
11112      new DeterministicSocketData(reads2, arraysize(reads2),
11113                                  writes2, arraysize(writes2)));
11114  MockConnect connect_data2(ASYNC, OK);
11115  data2->set_connect_data(connect_data2);
11116
11117  // Set up a proxy config that sends HTTP requests to a proxy, and
11118  // all others direct.
11119  ProxyConfig proxy_config;
11120  proxy_config.proxy_rules().ParseFromString("http=https://proxy:443");
11121  CapturingProxyResolver* capturing_proxy_resolver =
11122      new CapturingProxyResolver();
11123  session_deps_.proxy_service.reset(new ProxyService(
11124      new ProxyConfigServiceFixed(proxy_config), capturing_proxy_resolver,
11125      NULL));
11126
11127  // Load a valid cert.  Note, that this does not need to
11128  // be valid for proxy because the MockSSLClientSocket does
11129  // not actually verify it.  But SpdySession will use this
11130  // to see if it is valid for the new origin
11131  base::FilePath certs_dir = GetTestCertsDirectory();
11132  scoped_refptr<X509Certificate> server_cert(
11133      ImportCertFromFile(certs_dir, "ok_cert.pem"));
11134  ASSERT_NE(static_cast<X509Certificate*>(NULL), server_cert);
11135
11136  SSLSocketDataProvider ssl1(ASYNC, OK);  // to the proxy
11137  ssl1.SetNextProto(GetParam());
11138  ssl1.cert = server_cert;
11139  session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl1);
11140  session_deps_.deterministic_socket_factory->AddSocketDataProvider(
11141      data1.get());
11142
11143  SSLSocketDataProvider ssl2(ASYNC, OK);  // to the server
11144  ssl2.SetNextProto(GetParam());
11145  session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2);
11146  session_deps_.deterministic_socket_factory->AddSocketDataProvider(
11147      data2.get());
11148
11149  session_deps_.host_resolver.reset(new MockCachingHostResolver());
11150  session_deps_.host_resolver->rules()->AddRule("mail.google.com", ip_addr);
11151  session_deps_.host_resolver->rules()->AddRule("proxy", ip_addr);
11152
11153  scoped_refptr<HttpNetworkSession> session(
11154      SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
11155
11156  // Start the first transaction to set up the SpdySession
11157  HttpRequestInfo request1;
11158  request1.method = "GET";
11159  request1.url = GURL(url1);
11160  request1.load_flags = 0;
11161  HttpNetworkTransaction trans1(LOWEST, session.get());
11162  TestCompletionCallback callback1;
11163  ASSERT_EQ(ERR_IO_PENDING,
11164            trans1.Start(&request1, callback1.callback(), BoundNetLog()));
11165  data1->RunFor(3);
11166
11167  ASSERT_TRUE(callback1.have_result());
11168  EXPECT_EQ(OK, callback1.WaitForResult());
11169  EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
11170
11171  // Now, start the HTTP request
11172  HttpRequestInfo request2;
11173  request2.method = "GET";
11174  request2.url = GURL(url2);
11175  request2.load_flags = 0;
11176  HttpNetworkTransaction trans2(MEDIUM, session.get());
11177  TestCompletionCallback callback2;
11178  EXPECT_EQ(ERR_IO_PENDING,
11179            trans2.Start(&request2, callback2.callback(), BoundNetLog()));
11180  base::MessageLoop::current()->RunUntilIdle();
11181  data2->RunFor(3);
11182
11183  ASSERT_TRUE(callback2.have_result());
11184  EXPECT_EQ(OK, callback2.WaitForResult());
11185  EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
11186}
11187
11188// Test to verify that a failed socket read (due to an ERR_CONNECTION_CLOSED
11189// error) in SPDY session, removes the socket from pool and closes the SPDY
11190// session. Verify that new url's from the same HttpNetworkSession (and a new
11191// SpdySession) do work. http://crbug.com/224701
11192TEST_P(HttpNetworkTransactionTest, ErrorSocketNotConnected) {
11193  const std::string https_url = "https://www.google.com/";
11194
11195  MockRead reads1[] = {
11196    MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED, 0)
11197  };
11198
11199  scoped_ptr<DeterministicSocketData> data1(
11200      new DeterministicSocketData(reads1, arraysize(reads1), NULL, 0));
11201  data1->SetStop(1);
11202
11203  scoped_ptr<SpdyFrame> req2(
11204      spdy_util_.ConstructSpdyGet(https_url.c_str(), false, 1, MEDIUM));
11205  MockWrite writes2[] = {
11206    CreateMockWrite(*req2, 0),
11207  };
11208
11209  scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11210  scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
11211  MockRead reads2[] = {
11212    CreateMockRead(*resp2, 1),
11213    CreateMockRead(*body2, 2),
11214    MockRead(ASYNC, OK, 3)  // EOF
11215  };
11216
11217  scoped_ptr<DeterministicSocketData> data2(
11218      new DeterministicSocketData(reads2, arraysize(reads2),
11219                                  writes2, arraysize(writes2)));
11220
11221  SSLSocketDataProvider ssl1(ASYNC, OK);
11222  ssl1.SetNextProto(GetParam());
11223  session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl1);
11224  session_deps_.deterministic_socket_factory->AddSocketDataProvider(
11225      data1.get());
11226
11227  SSLSocketDataProvider ssl2(ASYNC, OK);
11228  ssl2.SetNextProto(GetParam());
11229  session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2);
11230  session_deps_.deterministic_socket_factory->AddSocketDataProvider(
11231      data2.get());
11232
11233  scoped_refptr<HttpNetworkSession> session(
11234      SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
11235
11236  // Start the first transaction to set up the SpdySession and verify that
11237  // connection was closed.
11238  HttpRequestInfo request1;
11239  request1.method = "GET";
11240  request1.url = GURL(https_url);
11241  request1.load_flags = 0;
11242  HttpNetworkTransaction trans1(MEDIUM, session.get());
11243  TestCompletionCallback callback1;
11244  EXPECT_EQ(ERR_IO_PENDING,
11245            trans1.Start(&request1, callback1.callback(), BoundNetLog()));
11246  base::MessageLoop::current()->RunUntilIdle();
11247  EXPECT_EQ(ERR_CONNECTION_CLOSED, callback1.WaitForResult());
11248
11249  // Now, start the second request and make sure it succeeds.
11250  HttpRequestInfo request2;
11251  request2.method = "GET";
11252  request2.url = GURL(https_url);
11253  request2.load_flags = 0;
11254  HttpNetworkTransaction trans2(MEDIUM, session.get());
11255  TestCompletionCallback callback2;
11256  EXPECT_EQ(ERR_IO_PENDING,
11257            trans2.Start(&request2, callback2.callback(), BoundNetLog()));
11258  base::MessageLoop::current()->RunUntilIdle();
11259  data2->RunFor(3);
11260
11261  ASSERT_TRUE(callback2.have_result());
11262  EXPECT_EQ(OK, callback2.WaitForResult());
11263  EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
11264}
11265
11266TEST_P(HttpNetworkTransactionTest, CloseIdleSpdySessionToOpenNewOne) {
11267  HttpStreamFactory::SetNextProtos(SpdyNextProtos());
11268  ClientSocketPoolManager::set_max_sockets_per_group(
11269      HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
11270  ClientSocketPoolManager::set_max_sockets_per_pool(
11271      HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
11272
11273  // Use two different hosts with different IPs so they don't get pooled.
11274  session_deps_.host_resolver->rules()->AddRule("www.a.com", "10.0.0.1");
11275  session_deps_.host_resolver->rules()->AddRule("www.b.com", "10.0.0.2");
11276  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11277
11278  SSLSocketDataProvider ssl1(ASYNC, OK);
11279  ssl1.SetNextProto(GetParam());
11280  SSLSocketDataProvider ssl2(ASYNC, OK);
11281  ssl2.SetNextProto(GetParam());
11282  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
11283  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
11284
11285  scoped_ptr<SpdyFrame> host1_req(spdy_util_.ConstructSpdyGet(
11286      "https://www.a.com", false, 1, DEFAULT_PRIORITY));
11287  MockWrite spdy1_writes[] = {
11288    CreateMockWrite(*host1_req, 1),
11289  };
11290  scoped_ptr<SpdyFrame> host1_resp(
11291      spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11292  scoped_ptr<SpdyFrame> host1_resp_body(
11293      spdy_util_.ConstructSpdyBodyFrame(1, true));
11294  MockRead spdy1_reads[] = {
11295    CreateMockRead(*host1_resp, 2),
11296    CreateMockRead(*host1_resp_body, 3),
11297    MockRead(ASYNC, ERR_IO_PENDING, 4),
11298  };
11299
11300  scoped_ptr<OrderedSocketData> spdy1_data(
11301      new OrderedSocketData(
11302          spdy1_reads, arraysize(spdy1_reads),
11303          spdy1_writes, arraysize(spdy1_writes)));
11304  session_deps_.socket_factory->AddSocketDataProvider(spdy1_data.get());
11305
11306  scoped_ptr<SpdyFrame> host2_req(spdy_util_.ConstructSpdyGet(
11307      "https://www.b.com", false, 1, DEFAULT_PRIORITY));
11308  MockWrite spdy2_writes[] = {
11309    CreateMockWrite(*host2_req, 1),
11310  };
11311  scoped_ptr<SpdyFrame> host2_resp(
11312      spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11313  scoped_ptr<SpdyFrame> host2_resp_body(
11314      spdy_util_.ConstructSpdyBodyFrame(1, true));
11315  MockRead spdy2_reads[] = {
11316    CreateMockRead(*host2_resp, 2),
11317    CreateMockRead(*host2_resp_body, 3),
11318    MockRead(ASYNC, ERR_IO_PENDING, 4),
11319  };
11320
11321  scoped_ptr<OrderedSocketData> spdy2_data(
11322      new OrderedSocketData(
11323          spdy2_reads, arraysize(spdy2_reads),
11324          spdy2_writes, arraysize(spdy2_writes)));
11325  session_deps_.socket_factory->AddSocketDataProvider(spdy2_data.get());
11326
11327  MockWrite http_write[] = {
11328    MockWrite("GET / HTTP/1.1\r\n"
11329              "Host: www.a.com\r\n"
11330              "Connection: keep-alive\r\n\r\n"),
11331  };
11332
11333  MockRead http_read[] = {
11334    MockRead("HTTP/1.1 200 OK\r\n"),
11335    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11336    MockRead("Content-Length: 6\r\n\r\n"),
11337    MockRead("hello!"),
11338  };
11339  StaticSocketDataProvider http_data(http_read, arraysize(http_read),
11340                                     http_write, arraysize(http_write));
11341  session_deps_.socket_factory->AddSocketDataProvider(&http_data);
11342
11343  HostPortPair host_port_pair_a("www.a.com", 443);
11344  SpdySessionKey spdy_session_key_a(
11345      host_port_pair_a, ProxyServer::Direct(), kPrivacyModeDisabled);
11346  EXPECT_FALSE(
11347      HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
11348
11349  TestCompletionCallback callback;
11350  HttpRequestInfo request1;
11351  request1.method = "GET";
11352  request1.url = GURL("https://www.a.com/");
11353  request1.load_flags = 0;
11354  scoped_ptr<HttpNetworkTransaction> trans(
11355      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
11356
11357  int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
11358  EXPECT_EQ(ERR_IO_PENDING, rv);
11359  EXPECT_EQ(OK, callback.WaitForResult());
11360
11361  const HttpResponseInfo* response = trans->GetResponseInfo();
11362  ASSERT_TRUE(response != NULL);
11363  ASSERT_TRUE(response->headers.get() != NULL);
11364  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11365  EXPECT_TRUE(response->was_fetched_via_spdy);
11366  EXPECT_TRUE(response->was_npn_negotiated);
11367
11368  std::string response_data;
11369  ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
11370  EXPECT_EQ("hello!", response_data);
11371  trans.reset();
11372  EXPECT_TRUE(
11373      HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
11374
11375  HostPortPair host_port_pair_b("www.b.com", 443);
11376  SpdySessionKey spdy_session_key_b(
11377      host_port_pair_b, ProxyServer::Direct(), kPrivacyModeDisabled);
11378  EXPECT_FALSE(
11379      HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
11380  HttpRequestInfo request2;
11381  request2.method = "GET";
11382  request2.url = GURL("https://www.b.com/");
11383  request2.load_flags = 0;
11384  trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
11385
11386  rv = trans->Start(&request2, callback.callback(), BoundNetLog());
11387  EXPECT_EQ(ERR_IO_PENDING, rv);
11388  EXPECT_EQ(OK, callback.WaitForResult());
11389
11390  response = trans->GetResponseInfo();
11391  ASSERT_TRUE(response != NULL);
11392  ASSERT_TRUE(response->headers.get() != NULL);
11393  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11394  EXPECT_TRUE(response->was_fetched_via_spdy);
11395  EXPECT_TRUE(response->was_npn_negotiated);
11396  ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
11397  EXPECT_EQ("hello!", response_data);
11398  EXPECT_FALSE(
11399      HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
11400  EXPECT_TRUE(
11401      HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
11402
11403  HostPortPair host_port_pair_a1("www.a.com", 80);
11404  SpdySessionKey spdy_session_key_a1(
11405      host_port_pair_a1, ProxyServer::Direct(), kPrivacyModeDisabled);
11406  EXPECT_FALSE(
11407      HasSpdySession(session->spdy_session_pool(), spdy_session_key_a1));
11408  HttpRequestInfo request3;
11409  request3.method = "GET";
11410  request3.url = GURL("http://www.a.com/");
11411  request3.load_flags = 0;
11412  trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
11413
11414  rv = trans->Start(&request3, callback.callback(), BoundNetLog());
11415  EXPECT_EQ(ERR_IO_PENDING, rv);
11416  EXPECT_EQ(OK, callback.WaitForResult());
11417
11418  response = trans->GetResponseInfo();
11419  ASSERT_TRUE(response != NULL);
11420  ASSERT_TRUE(response->headers.get() != NULL);
11421  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11422  EXPECT_FALSE(response->was_fetched_via_spdy);
11423  EXPECT_FALSE(response->was_npn_negotiated);
11424  ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
11425  EXPECT_EQ("hello!", response_data);
11426  EXPECT_FALSE(
11427      HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
11428  EXPECT_FALSE(
11429      HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
11430}
11431
11432TEST_P(HttpNetworkTransactionTest, HttpSyncConnectError) {
11433  HttpRequestInfo request;
11434  request.method = "GET";
11435  request.url = GURL("http://www.google.com/");
11436  request.load_flags = 0;
11437
11438  scoped_ptr<HttpTransaction> trans(
11439      new HttpNetworkTransaction(DEFAULT_PRIORITY,
11440                                 CreateSession(&session_deps_)));
11441
11442  MockConnect mock_connect(SYNCHRONOUS, ERR_CONNECTION_REFUSED);
11443  StaticSocketDataProvider data;
11444  data.set_connect_data(mock_connect);
11445  session_deps_.socket_factory->AddSocketDataProvider(&data);
11446
11447  TestCompletionCallback callback;
11448
11449  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
11450  EXPECT_EQ(ERR_IO_PENDING, rv);
11451
11452  rv = callback.WaitForResult();
11453  EXPECT_EQ(ERR_CONNECTION_REFUSED, rv);
11454
11455  EXPECT_EQ(NULL, trans->GetResponseInfo());
11456
11457  // We don't care whether this succeeds or fails, but it shouldn't crash.
11458  HttpRequestHeaders request_headers;
11459  trans->GetFullRequestHeaders(&request_headers);
11460}
11461
11462TEST_P(HttpNetworkTransactionTest, HttpAsyncConnectError) {
11463  HttpRequestInfo request;
11464  request.method = "GET";
11465  request.url = GURL("http://www.google.com/");
11466  request.load_flags = 0;
11467
11468  scoped_ptr<HttpTransaction> trans(
11469      new HttpNetworkTransaction(DEFAULT_PRIORITY,
11470                                 CreateSession(&session_deps_)));
11471
11472  MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
11473  StaticSocketDataProvider data;
11474  data.set_connect_data(mock_connect);
11475  session_deps_.socket_factory->AddSocketDataProvider(&data);
11476
11477  TestCompletionCallback callback;
11478
11479  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
11480  EXPECT_EQ(ERR_IO_PENDING, rv);
11481
11482  rv = callback.WaitForResult();
11483  EXPECT_EQ(ERR_CONNECTION_REFUSED, rv);
11484
11485  EXPECT_EQ(NULL, trans->GetResponseInfo());
11486
11487  // We don't care whether this succeeds or fails, but it shouldn't crash.
11488  HttpRequestHeaders request_headers;
11489  trans->GetFullRequestHeaders(&request_headers);
11490}
11491
11492TEST_P(HttpNetworkTransactionTest, HttpSyncWriteError) {
11493  HttpRequestInfo request;
11494  request.method = "GET";
11495  request.url = GURL("http://www.google.com/");
11496  request.load_flags = 0;
11497
11498  scoped_ptr<HttpTransaction> trans(
11499      new HttpNetworkTransaction(DEFAULT_PRIORITY,
11500                                 CreateSession(&session_deps_)));
11501
11502  MockWrite data_writes[] = {
11503    MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
11504  };
11505  MockRead data_reads[] = {
11506    MockRead(SYNCHRONOUS, ERR_UNEXPECTED),  // Should not be reached.
11507  };
11508
11509  StaticSocketDataProvider data(data_reads, arraysize(data_reads),
11510                                data_writes, arraysize(data_writes));
11511  session_deps_.socket_factory->AddSocketDataProvider(&data);
11512
11513  TestCompletionCallback callback;
11514
11515  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
11516  EXPECT_EQ(ERR_IO_PENDING, rv);
11517
11518  rv = callback.WaitForResult();
11519  EXPECT_EQ(ERR_CONNECTION_RESET, rv);
11520
11521  EXPECT_EQ(NULL, trans->GetResponseInfo());
11522
11523  HttpRequestHeaders request_headers;
11524  EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
11525  EXPECT_TRUE(request_headers.HasHeader("Host"));
11526}
11527
11528TEST_P(HttpNetworkTransactionTest, HttpAsyncWriteError) {
11529  HttpRequestInfo request;
11530  request.method = "GET";
11531  request.url = GURL("http://www.google.com/");
11532  request.load_flags = 0;
11533
11534  scoped_ptr<HttpTransaction> trans(
11535      new HttpNetworkTransaction(DEFAULT_PRIORITY,
11536                                 CreateSession(&session_deps_)));
11537
11538  MockWrite data_writes[] = {
11539    MockWrite(ASYNC, ERR_CONNECTION_RESET),
11540  };
11541  MockRead data_reads[] = {
11542    MockRead(SYNCHRONOUS, ERR_UNEXPECTED),  // Should not be reached.
11543  };
11544
11545  StaticSocketDataProvider data(data_reads, arraysize(data_reads),
11546                                data_writes, arraysize(data_writes));
11547  session_deps_.socket_factory->AddSocketDataProvider(&data);
11548
11549  TestCompletionCallback callback;
11550
11551  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
11552  EXPECT_EQ(ERR_IO_PENDING, rv);
11553
11554  rv = callback.WaitForResult();
11555  EXPECT_EQ(ERR_CONNECTION_RESET, rv);
11556
11557  EXPECT_EQ(NULL, trans->GetResponseInfo());
11558
11559  HttpRequestHeaders request_headers;
11560  EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
11561  EXPECT_TRUE(request_headers.HasHeader("Host"));
11562}
11563
11564TEST_P(HttpNetworkTransactionTest, HttpSyncReadError) {
11565  HttpRequestInfo request;
11566  request.method = "GET";
11567  request.url = GURL("http://www.google.com/");
11568  request.load_flags = 0;
11569
11570  scoped_ptr<HttpTransaction> trans(
11571      new HttpNetworkTransaction(DEFAULT_PRIORITY,
11572                                 CreateSession(&session_deps_)));
11573
11574  MockWrite data_writes[] = {
11575    MockWrite("GET / HTTP/1.1\r\n"
11576              "Host: www.google.com\r\n"
11577              "Connection: keep-alive\r\n\r\n"),
11578  };
11579  MockRead data_reads[] = {
11580    MockRead(SYNCHRONOUS, ERR_CONNECTION_RESET),
11581  };
11582
11583  StaticSocketDataProvider data(data_reads, arraysize(data_reads),
11584                                data_writes, arraysize(data_writes));
11585  session_deps_.socket_factory->AddSocketDataProvider(&data);
11586
11587  TestCompletionCallback callback;
11588
11589  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
11590  EXPECT_EQ(ERR_IO_PENDING, rv);
11591
11592  rv = callback.WaitForResult();
11593  EXPECT_EQ(ERR_CONNECTION_RESET, rv);
11594
11595  EXPECT_EQ(NULL, trans->GetResponseInfo());
11596
11597  HttpRequestHeaders request_headers;
11598  EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
11599  EXPECT_TRUE(request_headers.HasHeader("Host"));
11600}
11601
11602TEST_P(HttpNetworkTransactionTest, HttpAsyncReadError) {
11603  HttpRequestInfo request;
11604  request.method = "GET";
11605  request.url = GURL("http://www.google.com/");
11606  request.load_flags = 0;
11607
11608  scoped_ptr<HttpTransaction> trans(
11609      new HttpNetworkTransaction(DEFAULT_PRIORITY,
11610                                 CreateSession(&session_deps_)));
11611
11612  MockWrite data_writes[] = {
11613    MockWrite("GET / HTTP/1.1\r\n"
11614              "Host: www.google.com\r\n"
11615              "Connection: keep-alive\r\n\r\n"),
11616  };
11617  MockRead data_reads[] = {
11618    MockRead(ASYNC, ERR_CONNECTION_RESET),
11619  };
11620
11621  StaticSocketDataProvider data(data_reads, arraysize(data_reads),
11622                                data_writes, arraysize(data_writes));
11623  session_deps_.socket_factory->AddSocketDataProvider(&data);
11624
11625  TestCompletionCallback callback;
11626
11627  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
11628  EXPECT_EQ(ERR_IO_PENDING, rv);
11629
11630  rv = callback.WaitForResult();
11631  EXPECT_EQ(ERR_CONNECTION_RESET, rv);
11632
11633  EXPECT_EQ(NULL, trans->GetResponseInfo());
11634
11635  HttpRequestHeaders request_headers;
11636  EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
11637  EXPECT_TRUE(request_headers.HasHeader("Host"));
11638}
11639
11640TEST_P(HttpNetworkTransactionTest, GetFullRequestHeadersIncludesExtraHeader) {
11641  HttpRequestInfo request;
11642  request.method = "GET";
11643  request.url = GURL("http://www.google.com/");
11644  request.load_flags = 0;
11645  request.extra_headers.SetHeader("X-Foo", "bar");
11646
11647  scoped_ptr<HttpTransaction> trans(
11648      new HttpNetworkTransaction(DEFAULT_PRIORITY,
11649                                 CreateSession(&session_deps_)));
11650
11651  MockWrite data_writes[] = {
11652    MockWrite("GET / HTTP/1.1\r\n"
11653              "Host: www.google.com\r\n"
11654              "Connection: keep-alive\r\n"
11655              "X-Foo: bar\r\n\r\n"),
11656  };
11657  MockRead data_reads[] = {
11658    MockRead("HTTP/1.1 200 OK\r\n"
11659             "Content-Length: 5\r\n\r\n"
11660             "hello"),
11661    MockRead(ASYNC, ERR_UNEXPECTED),
11662  };
11663
11664  StaticSocketDataProvider data(data_reads, arraysize(data_reads),
11665                                data_writes, arraysize(data_writes));
11666  session_deps_.socket_factory->AddSocketDataProvider(&data);
11667
11668  TestCompletionCallback callback;
11669
11670  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
11671  EXPECT_EQ(ERR_IO_PENDING, rv);
11672
11673  rv = callback.WaitForResult();
11674  EXPECT_EQ(OK, rv);
11675
11676  HttpRequestHeaders request_headers;
11677  EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
11678  std::string foo;
11679  EXPECT_TRUE(request_headers.GetHeader("X-Foo", &foo));
11680  EXPECT_EQ("bar", foo);
11681}
11682
11683}  // namespace net
11684