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/files/file_path.h"
15#include "base/files/file_util.h"
16#include "base/json/json_writer.h"
17#include "base/memory/scoped_ptr.h"
18#include "base/memory/weak_ptr.h"
19#include "base/run_loop.h"
20#include "base/strings/string_util.h"
21#include "base/strings/utf_string_conversions.h"
22#include "base/test/test_file_util.h"
23#include "net/base/auth.h"
24#include "net/base/capturing_net_log.h"
25#include "net/base/completion_callback.h"
26#include "net/base/load_timing_info.h"
27#include "net/base/load_timing_info_test_util.h"
28#include "net/base/net_log.h"
29#include "net/base/net_log_unittest.h"
30#include "net/base/request_priority.h"
31#include "net/base/test_completion_callback.h"
32#include "net/base/test_data_directory.h"
33#include "net/base/upload_bytes_element_reader.h"
34#include "net/base/upload_data_stream.h"
35#include "net/base/upload_file_element_reader.h"
36#include "net/cert/mock_cert_verifier.h"
37#include "net/dns/host_cache.h"
38#include "net/dns/mock_host_resolver.h"
39#include "net/http/http_auth_challenge_tokenizer.h"
40#include "net/http/http_auth_handler_digest.h"
41#include "net/http/http_auth_handler_mock.h"
42#include "net/http/http_auth_handler_ntlm.h"
43#include "net/http/http_basic_stream.h"
44#include "net/http/http_network_session.h"
45#include "net/http/http_network_session_peer.h"
46#include "net/http/http_server_properties_impl.h"
47#include "net/http/http_stream.h"
48#include "net/http/http_stream_factory.h"
49#include "net/http/http_transaction_test_util.h"
50#include "net/proxy/proxy_config_service_fixed.h"
51#include "net/proxy/proxy_info.h"
52#include "net/proxy/proxy_resolver.h"
53#include "net/proxy/proxy_service.h"
54#include "net/socket/client_socket_factory.h"
55#include "net/socket/client_socket_pool_manager.h"
56#include "net/socket/mock_client_socket_pool_manager.h"
57#include "net/socket/next_proto.h"
58#include "net/socket/socket_test_util.h"
59#include "net/socket/ssl_client_socket.h"
60#include "net/spdy/spdy_framer.h"
61#include "net/spdy/spdy_session.h"
62#include "net/spdy/spdy_session_pool.h"
63#include "net/spdy/spdy_test_util_common.h"
64#include "net/ssl/ssl_cert_request_info.h"
65#include "net/ssl/ssl_config_service.h"
66#include "net/ssl/ssl_config_service_defaults.h"
67#include "net/ssl/ssl_info.h"
68#include "net/test/cert_test_util.h"
69#include "net/websockets/websocket_handshake_stream_base.h"
70#include "testing/gtest/include/gtest/gtest.h"
71#include "testing/platform_test.h"
72#include "url/gurl.h"
73
74using base::ASCIIToUTF16;
75
76//-----------------------------------------------------------------------------
77
78namespace {
79
80const base::string16 kBar(ASCIIToUTF16("bar"));
81const base::string16 kBar2(ASCIIToUTF16("bar2"));
82const base::string16 kBar3(ASCIIToUTF16("bar3"));
83const base::string16 kBaz(ASCIIToUTF16("baz"));
84const base::string16 kFirst(ASCIIToUTF16("first"));
85const base::string16 kFoo(ASCIIToUTF16("foo"));
86const base::string16 kFoo2(ASCIIToUTF16("foo2"));
87const base::string16 kFoo3(ASCIIToUTF16("foo3"));
88const base::string16 kFou(ASCIIToUTF16("fou"));
89const base::string16 kSecond(ASCIIToUTF16("second"));
90const base::string16 kTestingNTLM(ASCIIToUTF16("testing-ntlm"));
91const base::string16 kWrongPassword(ASCIIToUTF16("wrongpassword"));
92
93int GetIdleSocketCountInTransportSocketPool(net::HttpNetworkSession* session) {
94  return session->GetTransportSocketPool(
95      net::HttpNetworkSession::NORMAL_SOCKET_POOL)->IdleSocketCount();
96}
97
98int GetIdleSocketCountInSSLSocketPool(net::HttpNetworkSession* session) {
99  return session->GetSSLSocketPool(
100      net::HttpNetworkSession::NORMAL_SOCKET_POOL)->IdleSocketCount();
101}
102
103bool IsTransportSocketPoolStalled(net::HttpNetworkSession* session) {
104  return session->GetTransportSocketPool(
105      net::HttpNetworkSession::NORMAL_SOCKET_POOL)->IsStalled();
106}
107
108// Takes in a Value created from a NetLogHttpResponseParameter, and returns
109// a JSONified list of headers as a single string.  Uses single quotes instead
110// of double quotes for easier comparison.  Returns false on failure.
111bool GetHeaders(base::DictionaryValue* params, std::string* headers) {
112  if (!params)
113    return false;
114  base::ListValue* header_list;
115  if (!params->GetList("headers", &header_list))
116    return false;
117  std::string double_quote_headers;
118  base::JSONWriter::Write(header_list, &double_quote_headers);
119  base::ReplaceChars(double_quote_headers, "\"", "'", headers);
120  return true;
121}
122
123// Tests LoadTimingInfo in the case a socket is reused and no PAC script is
124// used.
125void TestLoadTimingReused(const net::LoadTimingInfo& load_timing_info) {
126  EXPECT_TRUE(load_timing_info.socket_reused);
127  EXPECT_NE(net::NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
128
129  EXPECT_TRUE(load_timing_info.proxy_resolve_start.is_null());
130  EXPECT_TRUE(load_timing_info.proxy_resolve_end.is_null());
131
132  net::ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
133  EXPECT_FALSE(load_timing_info.send_start.is_null());
134
135  EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
136
137  // Set at a higher level.
138  EXPECT_TRUE(load_timing_info.request_start_time.is_null());
139  EXPECT_TRUE(load_timing_info.request_start.is_null());
140  EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
141}
142
143// Tests LoadTimingInfo in the case a new socket is used and no PAC script is
144// used.
145void TestLoadTimingNotReused(const net::LoadTimingInfo& load_timing_info,
146                             int connect_timing_flags) {
147  EXPECT_FALSE(load_timing_info.socket_reused);
148  EXPECT_NE(net::NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
149
150  EXPECT_TRUE(load_timing_info.proxy_resolve_start.is_null());
151  EXPECT_TRUE(load_timing_info.proxy_resolve_end.is_null());
152
153  net::ExpectConnectTimingHasTimes(load_timing_info.connect_timing,
154                                   connect_timing_flags);
155  EXPECT_LE(load_timing_info.connect_timing.connect_end,
156            load_timing_info.send_start);
157
158  EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
159
160  // Set at a higher level.
161  EXPECT_TRUE(load_timing_info.request_start_time.is_null());
162  EXPECT_TRUE(load_timing_info.request_start.is_null());
163  EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
164}
165
166// Tests LoadTimingInfo in the case a socket is reused and a PAC script is
167// used.
168void TestLoadTimingReusedWithPac(const net::LoadTimingInfo& load_timing_info) {
169  EXPECT_TRUE(load_timing_info.socket_reused);
170  EXPECT_NE(net::NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
171
172  net::ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
173
174  EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null());
175  EXPECT_LE(load_timing_info.proxy_resolve_start,
176            load_timing_info.proxy_resolve_end);
177  EXPECT_LE(load_timing_info.proxy_resolve_end,
178            load_timing_info.send_start);
179  EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
180
181  // Set at a higher level.
182  EXPECT_TRUE(load_timing_info.request_start_time.is_null());
183  EXPECT_TRUE(load_timing_info.request_start.is_null());
184  EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
185}
186
187// Tests LoadTimingInfo in the case a new socket is used and a PAC script is
188// used.
189void TestLoadTimingNotReusedWithPac(const net::LoadTimingInfo& load_timing_info,
190                                    int connect_timing_flags) {
191  EXPECT_FALSE(load_timing_info.socket_reused);
192  EXPECT_NE(net::NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
193
194  EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null());
195  EXPECT_LE(load_timing_info.proxy_resolve_start,
196            load_timing_info.proxy_resolve_end);
197  EXPECT_LE(load_timing_info.proxy_resolve_end,
198            load_timing_info.connect_timing.connect_start);
199  net::ExpectConnectTimingHasTimes(load_timing_info.connect_timing,
200                                   connect_timing_flags);
201  EXPECT_LE(load_timing_info.connect_timing.connect_end,
202            load_timing_info.send_start);
203
204  EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
205
206  // Set at a higher level.
207  EXPECT_TRUE(load_timing_info.request_start_time.is_null());
208  EXPECT_TRUE(load_timing_info.request_start.is_null());
209  EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
210}
211
212}  // namespace
213
214namespace net {
215
216namespace {
217
218HttpNetworkSession* CreateSession(SpdySessionDependencies* session_deps) {
219  return SpdySessionDependencies::SpdyCreateSession(session_deps);
220}
221
222}  // namespace
223
224class HttpNetworkTransactionTest
225    : public PlatformTest,
226      public ::testing::WithParamInterface<NextProto> {
227 public:
228  virtual ~HttpNetworkTransactionTest() {
229    // Important to restore the per-pool limit first, since the pool limit must
230    // always be greater than group limit, and the tests reduce both limits.
231    ClientSocketPoolManager::set_max_sockets_per_pool(
232        HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_pool_sockets_);
233    ClientSocketPoolManager::set_max_sockets_per_group(
234        HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_group_sockets_);
235  }
236
237 protected:
238  HttpNetworkTransactionTest()
239      : spdy_util_(GetParam()),
240        session_deps_(GetParam()),
241        old_max_group_sockets_(ClientSocketPoolManager::max_sockets_per_group(
242            HttpNetworkSession::NORMAL_SOCKET_POOL)),
243        old_max_pool_sockets_(ClientSocketPoolManager::max_sockets_per_pool(
244            HttpNetworkSession::NORMAL_SOCKET_POOL)) {
245  }
246
247  struct SimpleGetHelperResult {
248    int rv;
249    std::string status_line;
250    std::string response_data;
251    int64 totalReceivedBytes;
252    LoadTimingInfo load_timing_info;
253  };
254
255  virtual void SetUp() {
256    NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
257    base::MessageLoop::current()->RunUntilIdle();
258  }
259
260  virtual void TearDown() {
261    NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
262    base::MessageLoop::current()->RunUntilIdle();
263    // Empty the current queue.
264    base::MessageLoop::current()->RunUntilIdle();
265    PlatformTest::TearDown();
266    NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
267    base::MessageLoop::current()->RunUntilIdle();
268  }
269
270  // This is the expected return from a current server advertising SPDY.
271  std::string GetAlternateProtocolHttpHeader() {
272    return
273        std::string("Alternate-Protocol: 443:") +
274        AlternateProtocolToString(AlternateProtocolFromNextProto(GetParam())) +
275        "\r\n\r\n";
276  }
277
278  // Either |write_failure| specifies a write failure or |read_failure|
279  // specifies a read failure when using a reused socket.  In either case, the
280  // failure should cause the network transaction to resend the request, and the
281  // other argument should be NULL.
282  void KeepAliveConnectionResendRequestTest(const MockWrite* write_failure,
283                                            const MockRead* read_failure);
284
285  // Either |write_failure| specifies a write failure or |read_failure|
286  // specifies a read failure when using a reused socket.  In either case, the
287  // failure should cause the network transaction to resend the request, and the
288  // other argument should be NULL.
289  void PreconnectErrorResendRequestTest(const MockWrite* write_failure,
290                                        const MockRead* read_failure,
291                                        bool use_spdy);
292
293  SimpleGetHelperResult SimpleGetHelperForData(StaticSocketDataProvider* data[],
294                                               size_t data_count) {
295    SimpleGetHelperResult out;
296
297    HttpRequestInfo request;
298    request.method = "GET";
299    request.url = GURL("http://www.google.com/");
300    request.load_flags = 0;
301
302    CapturingBoundNetLog log;
303    session_deps_.net_log = log.bound().net_log();
304    scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
305    scoped_ptr<HttpTransaction> trans(
306        new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
307
308    for (size_t i = 0; i < data_count; ++i) {
309      session_deps_.socket_factory->AddSocketDataProvider(data[i]);
310    }
311
312    TestCompletionCallback callback;
313
314    EXPECT_TRUE(log.bound().IsLogging());
315    int rv = trans->Start(&request, callback.callback(), log.bound());
316    EXPECT_EQ(ERR_IO_PENDING, rv);
317
318    out.rv = callback.WaitForResult();
319
320    // Even in the failure cases that use this function, connections are always
321    // successfully established before the error.
322    EXPECT_TRUE(trans->GetLoadTimingInfo(&out.load_timing_info));
323    TestLoadTimingNotReused(out.load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
324
325    if (out.rv != OK)
326      return out;
327
328    const HttpResponseInfo* response = trans->GetResponseInfo();
329    // Can't use ASSERT_* inside helper functions like this, so
330    // return an error.
331    if (response == NULL || response->headers.get() == NULL) {
332      out.rv = ERR_UNEXPECTED;
333      return out;
334    }
335    out.status_line = response->headers->GetStatusLine();
336
337    EXPECT_EQ("127.0.0.1", response->socket_address.host());
338    EXPECT_EQ(80, response->socket_address.port());
339
340    rv = ReadTransaction(trans.get(), &out.response_data);
341    EXPECT_EQ(OK, rv);
342
343    net::CapturingNetLog::CapturedEntryList entries;
344    log.GetEntries(&entries);
345    size_t pos = ExpectLogContainsSomewhere(
346        entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS,
347        NetLog::PHASE_NONE);
348    ExpectLogContainsSomewhere(
349        entries, pos,
350        NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS,
351        NetLog::PHASE_NONE);
352
353    std::string line;
354    EXPECT_TRUE(entries[pos].GetStringValue("line", &line));
355    EXPECT_EQ("GET / HTTP/1.1\r\n", line);
356
357    HttpRequestHeaders request_headers;
358    EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
359    std::string value;
360    EXPECT_TRUE(request_headers.GetHeader("Host", &value));
361    EXPECT_EQ("www.google.com", value);
362    EXPECT_TRUE(request_headers.GetHeader("Connection", &value));
363    EXPECT_EQ("keep-alive", value);
364
365    std::string response_headers;
366    EXPECT_TRUE(GetHeaders(entries[pos].params.get(), &response_headers));
367    EXPECT_EQ("['Host: www.google.com','Connection: keep-alive']",
368              response_headers);
369
370    out.totalReceivedBytes = trans->GetTotalReceivedBytes();
371    return out;
372  }
373
374  SimpleGetHelperResult SimpleGetHelper(MockRead data_reads[],
375                                        size_t reads_count) {
376    StaticSocketDataProvider reads(data_reads, reads_count, NULL, 0);
377    StaticSocketDataProvider* data[] = { &reads };
378    return SimpleGetHelperForData(data, 1);
379  }
380
381  int64 ReadsSize(MockRead data_reads[], size_t reads_count) {
382    int64 size = 0;
383    for (size_t i = 0; i < reads_count; ++i)
384      size += data_reads[i].data_len;
385    return size;
386  }
387
388  void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
389                                             int expected_status);
390
391  void ConnectStatusHelper(const MockRead& status);
392
393  void BypassHostCacheOnRefreshHelper(int load_flags);
394
395  void CheckErrorIsPassedBack(int error, IoMode mode);
396
397  SpdyTestUtil spdy_util_;
398  SpdySessionDependencies session_deps_;
399
400  // Original socket limits.  Some tests set these.  Safest to always restore
401  // them once each test has been run.
402  int old_max_group_sockets_;
403  int old_max_pool_sockets_;
404};
405
406INSTANTIATE_TEST_CASE_P(
407    NextProto,
408    HttpNetworkTransactionTest,
409    testing::Values(kProtoDeprecatedSPDY2,
410                    kProtoSPDY3, kProtoSPDY31, kProtoSPDY4));
411
412namespace {
413
414class BeforeNetworkStartHandler {
415 public:
416  explicit BeforeNetworkStartHandler(bool defer)
417      : defer_on_before_network_start_(defer),
418        observed_before_network_start_(false) {}
419
420  void OnBeforeNetworkStart(bool* defer) {
421    *defer = defer_on_before_network_start_;
422    observed_before_network_start_ = true;
423  }
424
425  bool observed_before_network_start() const {
426    return observed_before_network_start_;
427  }
428
429 private:
430  const bool defer_on_before_network_start_;
431  bool observed_before_network_start_;
432
433  DISALLOW_COPY_AND_ASSIGN(BeforeNetworkStartHandler);
434};
435
436class BeforeProxyHeadersSentHandler {
437 public:
438  BeforeProxyHeadersSentHandler()
439      : observed_before_proxy_headers_sent_(false) {}
440
441  void OnBeforeProxyHeadersSent(const ProxyInfo& proxy_info,
442                                HttpRequestHeaders* request_headers) {
443    observed_before_proxy_headers_sent_ = true;
444    observed_proxy_server_uri_ = proxy_info.proxy_server().ToURI();
445  }
446
447  bool observed_before_proxy_headers_sent() const {
448    return observed_before_proxy_headers_sent_;
449  }
450
451  std::string observed_proxy_server_uri() const {
452    return observed_proxy_server_uri_;
453  }
454
455 private:
456  bool observed_before_proxy_headers_sent_;
457  std::string observed_proxy_server_uri_;
458
459  DISALLOW_COPY_AND_ASSIGN(BeforeProxyHeadersSentHandler);
460};
461
462// Fill |str| with a long header list that consumes >= |size| bytes.
463void FillLargeHeadersString(std::string* str, int size) {
464  const char* row =
465      "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
466  const int sizeof_row = strlen(row);
467  const int num_rows = static_cast<int>(
468      ceil(static_cast<float>(size) / sizeof_row));
469  const int sizeof_data = num_rows * sizeof_row;
470  DCHECK(sizeof_data >= size);
471  str->reserve(sizeof_data);
472
473  for (int i = 0; i < num_rows; ++i)
474    str->append(row, sizeof_row);
475}
476
477// Alternative functions that eliminate randomness and dependency on the local
478// host name so that the generated NTLM messages are reproducible.
479void MockGenerateRandom1(uint8* output, size_t n) {
480  static const uint8 bytes[] = {
481    0x55, 0x29, 0x66, 0x26, 0x6b, 0x9c, 0x73, 0x54
482  };
483  static size_t current_byte = 0;
484  for (size_t i = 0; i < n; ++i) {
485    output[i] = bytes[current_byte++];
486    current_byte %= arraysize(bytes);
487  }
488}
489
490void MockGenerateRandom2(uint8* output, size_t n) {
491  static const uint8 bytes[] = {
492    0x96, 0x79, 0x85, 0xe7, 0x49, 0x93, 0x70, 0xa1,
493    0x4e, 0xe7, 0x87, 0x45, 0x31, 0x5b, 0xd3, 0x1f
494  };
495  static size_t current_byte = 0;
496  for (size_t i = 0; i < n; ++i) {
497    output[i] = bytes[current_byte++];
498    current_byte %= arraysize(bytes);
499  }
500}
501
502std::string MockGetHostName() {
503  return "WTC-WIN7";
504}
505
506template<typename ParentPool>
507class CaptureGroupNameSocketPool : public ParentPool {
508 public:
509  CaptureGroupNameSocketPool(HostResolver* host_resolver,
510                             CertVerifier* cert_verifier);
511
512  const std::string last_group_name_received() const {
513    return last_group_name_;
514  }
515
516  virtual int RequestSocket(const std::string& group_name,
517                            const void* socket_params,
518                            RequestPriority priority,
519                            ClientSocketHandle* handle,
520                            const CompletionCallback& callback,
521                            const BoundNetLog& net_log) {
522    last_group_name_ = group_name;
523    return ERR_IO_PENDING;
524  }
525  virtual void CancelRequest(const std::string& group_name,
526                             ClientSocketHandle* handle) {}
527  virtual void ReleaseSocket(const std::string& group_name,
528                             scoped_ptr<StreamSocket> socket,
529                             int id) {}
530  virtual void CloseIdleSockets() {}
531  virtual int IdleSocketCount() const {
532    return 0;
533  }
534  virtual int IdleSocketCountInGroup(const std::string& group_name) const {
535    return 0;
536  }
537  virtual LoadState GetLoadState(const std::string& group_name,
538                                 const ClientSocketHandle* handle) const {
539    return LOAD_STATE_IDLE;
540  }
541  virtual base::TimeDelta ConnectionTimeout() const {
542    return base::TimeDelta();
543  }
544
545 private:
546  std::string last_group_name_;
547};
548
549typedef CaptureGroupNameSocketPool<TransportClientSocketPool>
550CaptureGroupNameTransportSocketPool;
551typedef CaptureGroupNameSocketPool<HttpProxyClientSocketPool>
552CaptureGroupNameHttpProxySocketPool;
553typedef CaptureGroupNameSocketPool<SOCKSClientSocketPool>
554CaptureGroupNameSOCKSSocketPool;
555typedef CaptureGroupNameSocketPool<SSLClientSocketPool>
556CaptureGroupNameSSLSocketPool;
557
558template<typename ParentPool>
559CaptureGroupNameSocketPool<ParentPool>::CaptureGroupNameSocketPool(
560    HostResolver* host_resolver,
561    CertVerifier* /* cert_verifier */)
562    : ParentPool(0, 0, NULL, host_resolver, NULL, NULL) {}
563
564template<>
565CaptureGroupNameHttpProxySocketPool::CaptureGroupNameSocketPool(
566    HostResolver* host_resolver,
567    CertVerifier* /* cert_verifier */)
568    : HttpProxyClientSocketPool(
569          0, 0, NULL, host_resolver, NULL, NULL, NULL, NULL) {}
570
571template <>
572CaptureGroupNameSSLSocketPool::CaptureGroupNameSocketPool(
573    HostResolver* host_resolver,
574    CertVerifier* cert_verifier)
575    : SSLClientSocketPool(0,
576                          0,
577                          NULL,
578                          host_resolver,
579                          cert_verifier,
580                          NULL,
581                          NULL,
582                          NULL,
583                          std::string(),
584                          NULL,
585                          NULL,
586                          NULL,
587                          NULL,
588                          NULL,
589                          false,
590                          NULL) {
591}
592
593//-----------------------------------------------------------------------------
594
595// Helper functions for validating that AuthChallengeInfo's are correctly
596// configured for common cases.
597bool CheckBasicServerAuth(const AuthChallengeInfo* auth_challenge) {
598  if (!auth_challenge)
599    return false;
600  EXPECT_FALSE(auth_challenge->is_proxy);
601  EXPECT_EQ("www.google.com:80", auth_challenge->challenger.ToString());
602  EXPECT_EQ("MyRealm1", auth_challenge->realm);
603  EXPECT_EQ("basic", auth_challenge->scheme);
604  return true;
605}
606
607bool CheckBasicProxyAuth(const AuthChallengeInfo* auth_challenge) {
608  if (!auth_challenge)
609    return false;
610  EXPECT_TRUE(auth_challenge->is_proxy);
611  EXPECT_EQ("myproxy:70", auth_challenge->challenger.ToString());
612  EXPECT_EQ("MyRealm1", auth_challenge->realm);
613  EXPECT_EQ("basic", auth_challenge->scheme);
614  return true;
615}
616
617bool CheckDigestServerAuth(const AuthChallengeInfo* auth_challenge) {
618  if (!auth_challenge)
619    return false;
620  EXPECT_FALSE(auth_challenge->is_proxy);
621  EXPECT_EQ("www.google.com:80", auth_challenge->challenger.ToString());
622  EXPECT_EQ("digestive", auth_challenge->realm);
623  EXPECT_EQ("digest", auth_challenge->scheme);
624  return true;
625}
626
627bool CheckNTLMServerAuth(const AuthChallengeInfo* auth_challenge) {
628  if (!auth_challenge)
629    return false;
630  EXPECT_FALSE(auth_challenge->is_proxy);
631  EXPECT_EQ("172.22.68.17:80", auth_challenge->challenger.ToString());
632  EXPECT_EQ(std::string(), auth_challenge->realm);
633  EXPECT_EQ("ntlm", auth_challenge->scheme);
634  return true;
635}
636
637}  // namespace
638
639TEST_P(HttpNetworkTransactionTest, Basic) {
640  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
641  scoped_ptr<HttpTransaction> trans(
642      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
643}
644
645TEST_P(HttpNetworkTransactionTest, SimpleGET) {
646  MockRead data_reads[] = {
647    MockRead("HTTP/1.0 200 OK\r\n\r\n"),
648    MockRead("hello world"),
649    MockRead(SYNCHRONOUS, OK),
650  };
651  SimpleGetHelperResult out = SimpleGetHelper(data_reads,
652                                              arraysize(data_reads));
653  EXPECT_EQ(OK, out.rv);
654  EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
655  EXPECT_EQ("hello world", out.response_data);
656  int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
657  EXPECT_EQ(reads_size, out.totalReceivedBytes);
658}
659
660// Response with no status line.
661TEST_P(HttpNetworkTransactionTest, SimpleGETNoHeaders) {
662  MockRead data_reads[] = {
663    MockRead("hello world"),
664    MockRead(SYNCHRONOUS, OK),
665  };
666  SimpleGetHelperResult out = SimpleGetHelper(data_reads,
667                                              arraysize(data_reads));
668  EXPECT_EQ(OK, out.rv);
669  EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
670  EXPECT_EQ("hello world", out.response_data);
671  int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
672  EXPECT_EQ(reads_size, out.totalReceivedBytes);
673}
674
675// Allow up to 4 bytes of junk to precede status line.
676TEST_P(HttpNetworkTransactionTest, StatusLineJunk3Bytes) {
677  MockRead data_reads[] = {
678    MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
679    MockRead(SYNCHRONOUS, OK),
680  };
681  SimpleGetHelperResult out = SimpleGetHelper(data_reads,
682                                              arraysize(data_reads));
683  EXPECT_EQ(OK, out.rv);
684  EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
685  EXPECT_EQ("DATA", out.response_data);
686  int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
687  EXPECT_EQ(reads_size, out.totalReceivedBytes);
688}
689
690// Allow up to 4 bytes of junk to precede status line.
691TEST_P(HttpNetworkTransactionTest, StatusLineJunk4Bytes) {
692  MockRead data_reads[] = {
693    MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
694    MockRead(SYNCHRONOUS, OK),
695  };
696  SimpleGetHelperResult out = SimpleGetHelper(data_reads,
697                                              arraysize(data_reads));
698  EXPECT_EQ(OK, out.rv);
699  EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
700  EXPECT_EQ("DATA", out.response_data);
701  int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
702  EXPECT_EQ(reads_size, out.totalReceivedBytes);
703}
704
705// Beyond 4 bytes of slop and it should fail to find a status line.
706TEST_P(HttpNetworkTransactionTest, StatusLineJunk5Bytes) {
707  MockRead data_reads[] = {
708    MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
709    MockRead(SYNCHRONOUS, OK),
710  };
711  SimpleGetHelperResult out = SimpleGetHelper(data_reads,
712                                              arraysize(data_reads));
713  EXPECT_EQ(OK, out.rv);
714  EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
715  EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data);
716  int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
717  EXPECT_EQ(reads_size, out.totalReceivedBytes);
718}
719
720// Same as StatusLineJunk4Bytes, except the read chunks are smaller.
721TEST_P(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) {
722  MockRead data_reads[] = {
723    MockRead("\n"),
724    MockRead("\n"),
725    MockRead("Q"),
726    MockRead("J"),
727    MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
728    MockRead(SYNCHRONOUS, OK),
729  };
730  SimpleGetHelperResult out = SimpleGetHelper(data_reads,
731                                              arraysize(data_reads));
732  EXPECT_EQ(OK, out.rv);
733  EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
734  EXPECT_EQ("DATA", out.response_data);
735  int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
736  EXPECT_EQ(reads_size, out.totalReceivedBytes);
737}
738
739// Close the connection before enough bytes to have a status line.
740TEST_P(HttpNetworkTransactionTest, StatusLinePartial) {
741  MockRead data_reads[] = {
742    MockRead("HTT"),
743    MockRead(SYNCHRONOUS, OK),
744  };
745  SimpleGetHelperResult out = SimpleGetHelper(data_reads,
746                                              arraysize(data_reads));
747  EXPECT_EQ(OK, out.rv);
748  EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
749  EXPECT_EQ("HTT", out.response_data);
750  int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
751  EXPECT_EQ(reads_size, out.totalReceivedBytes);
752}
753
754// Simulate a 204 response, lacking a Content-Length header, sent over a
755// persistent connection.  The response should still terminate since a 204
756// cannot have a response body.
757TEST_P(HttpNetworkTransactionTest, StopsReading204) {
758  char junk[] = "junk";
759  MockRead data_reads[] = {
760    MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
761    MockRead(junk),  // Should not be read!!
762    MockRead(SYNCHRONOUS, OK),
763  };
764  SimpleGetHelperResult out = SimpleGetHelper(data_reads,
765                                              arraysize(data_reads));
766  EXPECT_EQ(OK, out.rv);
767  EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line);
768  EXPECT_EQ("", out.response_data);
769  int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
770  int64 response_size = reads_size - strlen(junk);
771  EXPECT_EQ(response_size, out.totalReceivedBytes);
772}
773
774// A simple request using chunked encoding with some extra data after.
775TEST_P(HttpNetworkTransactionTest, ChunkedEncoding) {
776  std::string final_chunk = "0\r\n\r\n";
777  std::string extra_data = "HTTP/1.1 200 OK\r\n";
778  std::string last_read = final_chunk + extra_data;
779  MockRead data_reads[] = {
780    MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
781    MockRead("5\r\nHello\r\n"),
782    MockRead("1\r\n"),
783    MockRead(" \r\n"),
784    MockRead("5\r\nworld\r\n"),
785    MockRead(last_read.data()),
786    MockRead(SYNCHRONOUS, OK),
787  };
788  SimpleGetHelperResult out = SimpleGetHelper(data_reads,
789                                              arraysize(data_reads));
790  EXPECT_EQ(OK, out.rv);
791  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
792  EXPECT_EQ("Hello world", out.response_data);
793  int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
794  int64 response_size = reads_size - extra_data.size();
795  EXPECT_EQ(response_size, out.totalReceivedBytes);
796}
797
798// Next tests deal with http://crbug.com/56344.
799
800TEST_P(HttpNetworkTransactionTest,
801       MultipleContentLengthHeadersNoTransferEncoding) {
802  MockRead data_reads[] = {
803    MockRead("HTTP/1.1 200 OK\r\n"),
804    MockRead("Content-Length: 10\r\n"),
805    MockRead("Content-Length: 5\r\n\r\n"),
806  };
807  SimpleGetHelperResult out = SimpleGetHelper(data_reads,
808                                              arraysize(data_reads));
809  EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, out.rv);
810}
811
812TEST_P(HttpNetworkTransactionTest,
813       DuplicateContentLengthHeadersNoTransferEncoding) {
814  MockRead data_reads[] = {
815    MockRead("HTTP/1.1 200 OK\r\n"),
816    MockRead("Content-Length: 5\r\n"),
817    MockRead("Content-Length: 5\r\n\r\n"),
818    MockRead("Hello"),
819  };
820  SimpleGetHelperResult out = SimpleGetHelper(data_reads,
821                                              arraysize(data_reads));
822  EXPECT_EQ(OK, out.rv);
823  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
824  EXPECT_EQ("Hello", out.response_data);
825}
826
827TEST_P(HttpNetworkTransactionTest,
828       ComplexContentLengthHeadersNoTransferEncoding) {
829  // More than 2 dupes.
830  {
831    MockRead data_reads[] = {
832      MockRead("HTTP/1.1 200 OK\r\n"),
833      MockRead("Content-Length: 5\r\n"),
834      MockRead("Content-Length: 5\r\n"),
835      MockRead("Content-Length: 5\r\n\r\n"),
836      MockRead("Hello"),
837    };
838    SimpleGetHelperResult out = SimpleGetHelper(data_reads,
839                                                arraysize(data_reads));
840    EXPECT_EQ(OK, out.rv);
841    EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
842    EXPECT_EQ("Hello", out.response_data);
843  }
844  // HTTP/1.0
845  {
846    MockRead data_reads[] = {
847      MockRead("HTTP/1.0 200 OK\r\n"),
848      MockRead("Content-Length: 5\r\n"),
849      MockRead("Content-Length: 5\r\n"),
850      MockRead("Content-Length: 5\r\n\r\n"),
851      MockRead("Hello"),
852    };
853    SimpleGetHelperResult out = SimpleGetHelper(data_reads,
854                                                arraysize(data_reads));
855    EXPECT_EQ(OK, out.rv);
856    EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
857    EXPECT_EQ("Hello", out.response_data);
858  }
859  // 2 dupes and one mismatched.
860  {
861    MockRead data_reads[] = {
862      MockRead("HTTP/1.1 200 OK\r\n"),
863      MockRead("Content-Length: 10\r\n"),
864      MockRead("Content-Length: 10\r\n"),
865      MockRead("Content-Length: 5\r\n\r\n"),
866    };
867    SimpleGetHelperResult out = SimpleGetHelper(data_reads,
868                                                arraysize(data_reads));
869    EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, out.rv);
870  }
871}
872
873TEST_P(HttpNetworkTransactionTest,
874       MultipleContentLengthHeadersTransferEncoding) {
875  MockRead data_reads[] = {
876    MockRead("HTTP/1.1 200 OK\r\n"),
877    MockRead("Content-Length: 666\r\n"),
878    MockRead("Content-Length: 1337\r\n"),
879    MockRead("Transfer-Encoding: chunked\r\n\r\n"),
880    MockRead("5\r\nHello\r\n"),
881    MockRead("1\r\n"),
882    MockRead(" \r\n"),
883    MockRead("5\r\nworld\r\n"),
884    MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
885    MockRead(SYNCHRONOUS, OK),
886  };
887  SimpleGetHelperResult out = SimpleGetHelper(data_reads,
888                                              arraysize(data_reads));
889  EXPECT_EQ(OK, out.rv);
890  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
891  EXPECT_EQ("Hello world", out.response_data);
892}
893
894// Next tests deal with http://crbug.com/98895.
895
896// Checks that a single Content-Disposition header results in no error.
897TEST_P(HttpNetworkTransactionTest, SingleContentDispositionHeader) {
898  MockRead data_reads[] = {
899    MockRead("HTTP/1.1 200 OK\r\n"),
900    MockRead("Content-Disposition: attachment;filename=\"salutations.txt\"r\n"),
901    MockRead("Content-Length: 5\r\n\r\n"),
902    MockRead("Hello"),
903  };
904  SimpleGetHelperResult out = SimpleGetHelper(data_reads,
905                                              arraysize(data_reads));
906  EXPECT_EQ(OK, out.rv);
907  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
908  EXPECT_EQ("Hello", out.response_data);
909}
910
911// Checks that two identical Content-Disposition headers result in no error.
912TEST_P(HttpNetworkTransactionTest,
913       TwoIdenticalContentDispositionHeaders) {
914  MockRead data_reads[] = {
915    MockRead("HTTP/1.1 200 OK\r\n"),
916    MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
917    MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
918    MockRead("Content-Length: 5\r\n\r\n"),
919    MockRead("Hello"),
920  };
921  SimpleGetHelperResult out = SimpleGetHelper(data_reads,
922                                              arraysize(data_reads));
923  EXPECT_EQ(OK, out.rv);
924  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
925  EXPECT_EQ("Hello", out.response_data);
926}
927
928// Checks that two distinct Content-Disposition headers result in an error.
929TEST_P(HttpNetworkTransactionTest, TwoDistinctContentDispositionHeaders) {
930  MockRead data_reads[] = {
931    MockRead("HTTP/1.1 200 OK\r\n"),
932    MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
933    MockRead("Content-Disposition: attachment;filename=\"hi.txt\"r\n"),
934    MockRead("Content-Length: 5\r\n\r\n"),
935    MockRead("Hello"),
936  };
937  SimpleGetHelperResult out = SimpleGetHelper(data_reads,
938                                              arraysize(data_reads));
939  EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION, out.rv);
940}
941
942// Checks that two identical Location headers result in no error.
943// Also tests Location header behavior.
944TEST_P(HttpNetworkTransactionTest, TwoIdenticalLocationHeaders) {
945  MockRead data_reads[] = {
946    MockRead("HTTP/1.1 302 Redirect\r\n"),
947    MockRead("Location: http://good.com/\r\n"),
948    MockRead("Location: http://good.com/\r\n"),
949    MockRead("Content-Length: 0\r\n\r\n"),
950    MockRead(SYNCHRONOUS, OK),
951  };
952
953  HttpRequestInfo request;
954  request.method = "GET";
955  request.url = GURL("http://redirect.com/");
956  request.load_flags = 0;
957
958  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
959  scoped_ptr<HttpTransaction> trans(
960      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
961
962  StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
963  session_deps_.socket_factory->AddSocketDataProvider(&data);
964
965  TestCompletionCallback callback;
966
967  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
968  EXPECT_EQ(ERR_IO_PENDING, rv);
969
970  EXPECT_EQ(OK, callback.WaitForResult());
971
972  const HttpResponseInfo* response = trans->GetResponseInfo();
973  ASSERT_TRUE(response != NULL && response->headers.get() != NULL);
974  EXPECT_EQ("HTTP/1.1 302 Redirect", response->headers->GetStatusLine());
975  std::string url;
976  EXPECT_TRUE(response->headers->IsRedirect(&url));
977  EXPECT_EQ("http://good.com/", url);
978  EXPECT_TRUE(response->proxy_server.IsEmpty());
979}
980
981// Checks that two distinct Location headers result in an error.
982TEST_P(HttpNetworkTransactionTest, TwoDistinctLocationHeaders) {
983  MockRead data_reads[] = {
984    MockRead("HTTP/1.1 302 Redirect\r\n"),
985    MockRead("Location: http://good.com/\r\n"),
986    MockRead("Location: http://evil.com/\r\n"),
987    MockRead("Content-Length: 0\r\n\r\n"),
988    MockRead(SYNCHRONOUS, OK),
989  };
990  SimpleGetHelperResult out = SimpleGetHelper(data_reads,
991                                              arraysize(data_reads));
992  EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_LOCATION, out.rv);
993}
994
995// Do a request using the HEAD method. Verify that we don't try to read the
996// message body (since HEAD has none).
997TEST_P(HttpNetworkTransactionTest, Head) {
998  HttpRequestInfo request;
999  request.method = "HEAD";
1000  request.url = GURL("http://www.google.com/");
1001  request.load_flags = 0;
1002
1003  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1004  scoped_ptr<HttpTransaction> trans(
1005      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1006  BeforeProxyHeadersSentHandler proxy_headers_handler;
1007  trans->SetBeforeProxyHeadersSentCallback(
1008      base::Bind(&BeforeProxyHeadersSentHandler::OnBeforeProxyHeadersSent,
1009                 base::Unretained(&proxy_headers_handler)));
1010
1011  MockWrite data_writes1[] = {
1012    MockWrite("HEAD / HTTP/1.1\r\n"
1013              "Host: www.google.com\r\n"
1014              "Connection: keep-alive\r\n"
1015              "Content-Length: 0\r\n\r\n"),
1016  };
1017  MockRead data_reads1[] = {
1018    MockRead("HTTP/1.1 404 Not Found\r\n"),
1019    MockRead("Server: Blah\r\n"),
1020    MockRead("Content-Length: 1234\r\n\r\n"),
1021
1022    // No response body because the test stops reading here.
1023    MockRead(SYNCHRONOUS, ERR_UNEXPECTED),  // Should not be reached.
1024  };
1025
1026  StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1027                                 data_writes1, arraysize(data_writes1));
1028  session_deps_.socket_factory->AddSocketDataProvider(&data1);
1029
1030  TestCompletionCallback callback1;
1031
1032  int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
1033  EXPECT_EQ(ERR_IO_PENDING, rv);
1034
1035  rv = callback1.WaitForResult();
1036  EXPECT_EQ(OK, rv);
1037
1038  const HttpResponseInfo* response = trans->GetResponseInfo();
1039  ASSERT_TRUE(response != NULL);
1040
1041  // Check that the headers got parsed.
1042  EXPECT_TRUE(response->headers.get() != NULL);
1043  EXPECT_EQ(1234, response->headers->GetContentLength());
1044  EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine());
1045  EXPECT_TRUE(response->proxy_server.IsEmpty());
1046  EXPECT_FALSE(proxy_headers_handler.observed_before_proxy_headers_sent());
1047
1048  std::string server_header;
1049  void* iter = NULL;
1050  bool has_server_header = response->headers->EnumerateHeader(
1051      &iter, "Server", &server_header);
1052  EXPECT_TRUE(has_server_header);
1053  EXPECT_EQ("Blah", server_header);
1054
1055  // Reading should give EOF right away, since there is no message body
1056  // (despite non-zero content-length).
1057  std::string response_data;
1058  rv = ReadTransaction(trans.get(), &response_data);
1059  EXPECT_EQ(OK, rv);
1060  EXPECT_EQ("", response_data);
1061}
1062
1063TEST_P(HttpNetworkTransactionTest, ReuseConnection) {
1064  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1065
1066  MockRead data_reads[] = {
1067    MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1068    MockRead("hello"),
1069    MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1070    MockRead("world"),
1071    MockRead(SYNCHRONOUS, OK),
1072  };
1073  StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1074  session_deps_.socket_factory->AddSocketDataProvider(&data);
1075
1076  const char* const kExpectedResponseData[] = {
1077    "hello", "world"
1078  };
1079
1080  for (int i = 0; i < 2; ++i) {
1081    HttpRequestInfo request;
1082    request.method = "GET";
1083    request.url = GURL("http://www.google.com/");
1084    request.load_flags = 0;
1085
1086    scoped_ptr<HttpTransaction> trans(
1087        new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1088
1089    TestCompletionCallback callback;
1090
1091    int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1092    EXPECT_EQ(ERR_IO_PENDING, rv);
1093
1094    rv = callback.WaitForResult();
1095    EXPECT_EQ(OK, rv);
1096
1097    const HttpResponseInfo* response = trans->GetResponseInfo();
1098    ASSERT_TRUE(response != NULL);
1099
1100    EXPECT_TRUE(response->headers.get() != NULL);
1101    EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1102    EXPECT_TRUE(response->proxy_server.IsEmpty());
1103
1104    std::string response_data;
1105    rv = ReadTransaction(trans.get(), &response_data);
1106    EXPECT_EQ(OK, rv);
1107    EXPECT_EQ(kExpectedResponseData[i], response_data);
1108  }
1109}
1110
1111TEST_P(HttpNetworkTransactionTest, Ignores100) {
1112  ScopedVector<UploadElementReader> element_readers;
1113  element_readers.push_back(new UploadBytesElementReader("foo", 3));
1114  UploadDataStream upload_data_stream(element_readers.Pass(), 0);
1115
1116  HttpRequestInfo request;
1117  request.method = "POST";
1118  request.url = GURL("http://www.foo.com/");
1119  request.upload_data_stream = &upload_data_stream;
1120  request.load_flags = 0;
1121
1122  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1123  scoped_ptr<HttpTransaction> trans(
1124      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1125
1126  MockRead data_reads[] = {
1127    MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
1128    MockRead("HTTP/1.0 200 OK\r\n\r\n"),
1129    MockRead("hello world"),
1130    MockRead(SYNCHRONOUS, OK),
1131  };
1132  StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1133  session_deps_.socket_factory->AddSocketDataProvider(&data);
1134
1135  TestCompletionCallback callback;
1136
1137  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1138  EXPECT_EQ(ERR_IO_PENDING, rv);
1139
1140  rv = callback.WaitForResult();
1141  EXPECT_EQ(OK, rv);
1142
1143  const HttpResponseInfo* response = trans->GetResponseInfo();
1144  ASSERT_TRUE(response != NULL);
1145
1146  EXPECT_TRUE(response->headers.get() != NULL);
1147  EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
1148
1149  std::string response_data;
1150  rv = ReadTransaction(trans.get(), &response_data);
1151  EXPECT_EQ(OK, rv);
1152  EXPECT_EQ("hello world", response_data);
1153}
1154
1155// This test is almost the same as Ignores100 above, but the response contains
1156// a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
1157// HTTP/1.1 and the two status headers are read in one read.
1158TEST_P(HttpNetworkTransactionTest, Ignores1xx) {
1159  HttpRequestInfo request;
1160  request.method = "GET";
1161  request.url = GURL("http://www.foo.com/");
1162  request.load_flags = 0;
1163
1164  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1165  scoped_ptr<HttpTransaction> trans(
1166      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1167
1168  MockRead data_reads[] = {
1169    MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
1170             "HTTP/1.1 200 OK\r\n\r\n"),
1171    MockRead("hello world"),
1172    MockRead(SYNCHRONOUS, OK),
1173  };
1174  StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1175  session_deps_.socket_factory->AddSocketDataProvider(&data);
1176
1177  TestCompletionCallback callback;
1178
1179  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1180  EXPECT_EQ(ERR_IO_PENDING, rv);
1181
1182  rv = callback.WaitForResult();
1183  EXPECT_EQ(OK, rv);
1184
1185  const HttpResponseInfo* response = trans->GetResponseInfo();
1186  ASSERT_TRUE(response != NULL);
1187
1188  EXPECT_TRUE(response->headers.get() != NULL);
1189  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1190
1191  std::string response_data;
1192  rv = ReadTransaction(trans.get(), &response_data);
1193  EXPECT_EQ(OK, rv);
1194  EXPECT_EQ("hello world", response_data);
1195}
1196
1197TEST_P(HttpNetworkTransactionTest, Incomplete100ThenEOF) {
1198  HttpRequestInfo request;
1199  request.method = "POST";
1200  request.url = GURL("http://www.foo.com/");
1201  request.load_flags = 0;
1202
1203  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1204  scoped_ptr<HttpTransaction> trans(
1205      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1206
1207  MockRead data_reads[] = {
1208    MockRead(SYNCHRONOUS, "HTTP/1.0 100 Continue\r\n"),
1209    MockRead(ASYNC, 0),
1210  };
1211  StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1212  session_deps_.socket_factory->AddSocketDataProvider(&data);
1213
1214  TestCompletionCallback callback;
1215
1216  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1217  EXPECT_EQ(ERR_IO_PENDING, rv);
1218
1219  rv = callback.WaitForResult();
1220  EXPECT_EQ(OK, rv);
1221
1222  std::string response_data;
1223  rv = ReadTransaction(trans.get(), &response_data);
1224  EXPECT_EQ(OK, rv);
1225  EXPECT_EQ("", response_data);
1226}
1227
1228TEST_P(HttpNetworkTransactionTest, EmptyResponse) {
1229  HttpRequestInfo request;
1230  request.method = "POST";
1231  request.url = GURL("http://www.foo.com/");
1232  request.load_flags = 0;
1233
1234  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1235  scoped_ptr<HttpTransaction> trans(
1236      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1237
1238  MockRead data_reads[] = {
1239    MockRead(ASYNC, 0),
1240  };
1241  StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1242  session_deps_.socket_factory->AddSocketDataProvider(&data);
1243
1244  TestCompletionCallback callback;
1245
1246  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1247  EXPECT_EQ(ERR_IO_PENDING, rv);
1248
1249  rv = callback.WaitForResult();
1250  EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
1251}
1252
1253void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
1254    const MockWrite* write_failure,
1255    const MockRead* read_failure) {
1256  HttpRequestInfo request;
1257  request.method = "GET";
1258  request.url = GURL("http://www.foo.com/");
1259  request.load_flags = 0;
1260
1261  CapturingNetLog net_log;
1262  session_deps_.net_log = &net_log;
1263  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1264
1265  // Written data for successfully sending both requests.
1266  MockWrite data1_writes[] = {
1267    MockWrite("GET / HTTP/1.1\r\n"
1268              "Host: www.foo.com\r\n"
1269              "Connection: keep-alive\r\n\r\n"),
1270    MockWrite("GET / HTTP/1.1\r\n"
1271              "Host: www.foo.com\r\n"
1272              "Connection: keep-alive\r\n\r\n")
1273  };
1274
1275  // Read results for the first request.
1276  MockRead data1_reads[] = {
1277    MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1278    MockRead("hello"),
1279    MockRead(ASYNC, OK),
1280  };
1281
1282  if (write_failure) {
1283    ASSERT_FALSE(read_failure);
1284    data1_writes[1] = *write_failure;
1285  } else {
1286    ASSERT_TRUE(read_failure);
1287    data1_reads[2] = *read_failure;
1288  }
1289
1290  StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads),
1291                                 data1_writes, arraysize(data1_writes));
1292  session_deps_.socket_factory->AddSocketDataProvider(&data1);
1293
1294  MockRead data2_reads[] = {
1295    MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1296    MockRead("world"),
1297    MockRead(ASYNC, OK),
1298  };
1299  StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
1300  session_deps_.socket_factory->AddSocketDataProvider(&data2);
1301
1302  const char* kExpectedResponseData[] = {
1303    "hello", "world"
1304  };
1305
1306  uint32 first_socket_log_id = NetLog::Source::kInvalidId;
1307  for (int i = 0; i < 2; ++i) {
1308    TestCompletionCallback callback;
1309
1310    scoped_ptr<HttpTransaction> trans(
1311        new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1312
1313    int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1314    EXPECT_EQ(ERR_IO_PENDING, rv);
1315
1316    rv = callback.WaitForResult();
1317    EXPECT_EQ(OK, rv);
1318
1319    LoadTimingInfo load_timing_info;
1320    EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
1321    TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
1322    if (i == 0) {
1323      first_socket_log_id = load_timing_info.socket_log_id;
1324    } else {
1325      // The second request should be using a new socket.
1326      EXPECT_NE(first_socket_log_id, load_timing_info.socket_log_id);
1327    }
1328
1329    const HttpResponseInfo* response = trans->GetResponseInfo();
1330    ASSERT_TRUE(response != NULL);
1331
1332    EXPECT_TRUE(response->headers.get() != NULL);
1333    EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1334
1335    std::string response_data;
1336    rv = ReadTransaction(trans.get(), &response_data);
1337    EXPECT_EQ(OK, rv);
1338    EXPECT_EQ(kExpectedResponseData[i], response_data);
1339  }
1340}
1341
1342void HttpNetworkTransactionTest::PreconnectErrorResendRequestTest(
1343    const MockWrite* write_failure,
1344    const MockRead* read_failure,
1345    bool use_spdy) {
1346  HttpRequestInfo request;
1347  request.method = "GET";
1348  request.url = GURL("https://www.foo.com/");
1349  request.load_flags = 0;
1350
1351  CapturingNetLog net_log;
1352  session_deps_.net_log = &net_log;
1353  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1354
1355  SSLSocketDataProvider ssl1(ASYNC, OK);
1356  SSLSocketDataProvider ssl2(ASYNC, OK);
1357  if (use_spdy) {
1358    ssl1.SetNextProto(GetParam());
1359    ssl2.SetNextProto(GetParam());
1360  }
1361  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
1362  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
1363
1364  // SPDY versions of the request and response.
1365  scoped_ptr<SpdyFrame> spdy_request(spdy_util_.ConstructSpdyGet(
1366      request.url.spec().c_str(), false, 1, DEFAULT_PRIORITY));
1367  scoped_ptr<SpdyFrame> spdy_response(
1368      spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1369  scoped_ptr<SpdyFrame> spdy_data(
1370      spdy_util_.ConstructSpdyBodyFrame(1, "hello", 5, true));
1371
1372  // HTTP/1.1 versions of the request and response.
1373  const char kHttpRequest[] = "GET / HTTP/1.1\r\n"
1374      "Host: www.foo.com\r\n"
1375      "Connection: keep-alive\r\n\r\n";
1376  const char kHttpResponse[] = "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n";
1377  const char kHttpData[] = "hello";
1378
1379  std::vector<MockRead> data1_reads;
1380  std::vector<MockWrite> data1_writes;
1381  if (write_failure) {
1382    ASSERT_FALSE(read_failure);
1383    data1_writes.push_back(*write_failure);
1384    data1_reads.push_back(MockRead(ASYNC, OK));
1385  } else {
1386    ASSERT_TRUE(read_failure);
1387    if (use_spdy) {
1388      data1_writes.push_back(CreateMockWrite(*spdy_request));
1389    } else {
1390      data1_writes.push_back(MockWrite(kHttpRequest));
1391    }
1392    data1_reads.push_back(*read_failure);
1393  }
1394
1395  StaticSocketDataProvider data1(&data1_reads[0], data1_reads.size(),
1396                                 &data1_writes[0], data1_writes.size());
1397  session_deps_.socket_factory->AddSocketDataProvider(&data1);
1398
1399  std::vector<MockRead> data2_reads;
1400  std::vector<MockWrite> data2_writes;
1401
1402  if (use_spdy) {
1403    data2_writes.push_back(CreateMockWrite(*spdy_request, 0, ASYNC));
1404
1405    data2_reads.push_back(CreateMockRead(*spdy_response, 1, ASYNC));
1406    data2_reads.push_back(CreateMockRead(*spdy_data, 2, ASYNC));
1407    data2_reads.push_back(MockRead(ASYNC, OK, 3));
1408  } else {
1409    data2_writes.push_back(
1410        MockWrite(ASYNC, kHttpRequest, strlen(kHttpRequest), 0));
1411
1412    data2_reads.push_back(
1413        MockRead(ASYNC, kHttpResponse, strlen(kHttpResponse), 1));
1414    data2_reads.push_back(MockRead(ASYNC, kHttpData, strlen(kHttpData), 2));
1415    data2_reads.push_back(MockRead(ASYNC, OK, 3));
1416  }
1417  OrderedSocketData data2(&data2_reads[0], data2_reads.size(),
1418                          &data2_writes[0], data2_writes.size());
1419  session_deps_.socket_factory->AddSocketDataProvider(&data2);
1420
1421  // Preconnect a socket.
1422  net::SSLConfig ssl_config;
1423  session->ssl_config_service()->GetSSLConfig(&ssl_config);
1424  session->GetNextProtos(&ssl_config.next_protos);
1425  session->http_stream_factory()->PreconnectStreams(
1426      1, request, DEFAULT_PRIORITY, ssl_config, ssl_config);
1427  // Wait for the preconnect to complete.
1428  // TODO(davidben): Some way to wait for an idle socket count might be handy.
1429  base::RunLoop().RunUntilIdle();
1430  EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
1431
1432  // Make the request.
1433  TestCompletionCallback callback;
1434
1435  scoped_ptr<HttpTransaction> trans(
1436      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1437
1438  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1439  EXPECT_EQ(ERR_IO_PENDING, rv);
1440
1441  rv = callback.WaitForResult();
1442  EXPECT_EQ(OK, rv);
1443
1444  LoadTimingInfo load_timing_info;
1445  EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
1446  TestLoadTimingNotReused(
1447      load_timing_info,
1448      CONNECT_TIMING_HAS_DNS_TIMES|CONNECT_TIMING_HAS_SSL_TIMES);
1449
1450  const HttpResponseInfo* response = trans->GetResponseInfo();
1451  ASSERT_TRUE(response != NULL);
1452
1453  EXPECT_TRUE(response->headers.get() != NULL);
1454  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1455
1456  std::string response_data;
1457  rv = ReadTransaction(trans.get(), &response_data);
1458  EXPECT_EQ(OK, rv);
1459  EXPECT_EQ(kHttpData, response_data);
1460}
1461
1462TEST_P(HttpNetworkTransactionTest,
1463       KeepAliveConnectionNotConnectedOnWrite) {
1464  MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
1465  KeepAliveConnectionResendRequestTest(&write_failure, NULL);
1466}
1467
1468TEST_P(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
1469  MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
1470  KeepAliveConnectionResendRequestTest(NULL, &read_failure);
1471}
1472
1473TEST_P(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
1474  MockRead read_failure(SYNCHRONOUS, OK);  // EOF
1475  KeepAliveConnectionResendRequestTest(NULL, &read_failure);
1476}
1477
1478// Make sure that on a 408 response (Request Timeout), the request is retried,
1479// if the socket was a reused keep alive socket.
1480TEST_P(HttpNetworkTransactionTest, KeepAlive408) {
1481  MockRead read_failure(SYNCHRONOUS,
1482                        "HTTP/1.1 408 Request Timeout\r\n"
1483                        "Connection: Keep-Alive\r\n"
1484                        "Content-Length: 6\r\n\r\n"
1485                        "Pickle");
1486  KeepAliveConnectionResendRequestTest(NULL, &read_failure);
1487}
1488
1489TEST_P(HttpNetworkTransactionTest,
1490       PreconnectErrorNotConnectedOnWrite) {
1491  MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
1492  PreconnectErrorResendRequestTest(&write_failure, NULL, false);
1493}
1494
1495TEST_P(HttpNetworkTransactionTest, PreconnectErrorReset) {
1496  MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
1497  PreconnectErrorResendRequestTest(NULL, &read_failure, false);
1498}
1499
1500TEST_P(HttpNetworkTransactionTest, PreconnectErrorEOF) {
1501  MockRead read_failure(SYNCHRONOUS, OK);  // EOF
1502  PreconnectErrorResendRequestTest(NULL, &read_failure, false);
1503}
1504
1505TEST_P(HttpNetworkTransactionTest, PreconnectErrorAsyncEOF) {
1506  MockRead read_failure(ASYNC, OK);  // EOF
1507  PreconnectErrorResendRequestTest(NULL, &read_failure, false);
1508}
1509
1510// Make sure that on a 408 response (Request Timeout), the request is retried,
1511// if the socket was a preconnected (UNUSED_IDLE) socket.
1512TEST_P(HttpNetworkTransactionTest, RetryOnIdle408) {
1513  MockRead read_failure(SYNCHRONOUS,
1514                        "HTTP/1.1 408 Request Timeout\r\n"
1515                        "Connection: Keep-Alive\r\n"
1516                        "Content-Length: 6\r\n\r\n"
1517                        "Pickle");
1518  KeepAliveConnectionResendRequestTest(NULL, &read_failure);
1519  PreconnectErrorResendRequestTest(NULL, &read_failure, false);
1520}
1521
1522TEST_P(HttpNetworkTransactionTest,
1523       SpdyPreconnectErrorNotConnectedOnWrite) {
1524  MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
1525  PreconnectErrorResendRequestTest(&write_failure, NULL, true);
1526}
1527
1528TEST_P(HttpNetworkTransactionTest, SpdyPreconnectErrorReset) {
1529  MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
1530  PreconnectErrorResendRequestTest(NULL, &read_failure, true);
1531}
1532
1533TEST_P(HttpNetworkTransactionTest, SpdyPreconnectErrorEOF) {
1534  MockRead read_failure(SYNCHRONOUS, OK);  // EOF
1535  PreconnectErrorResendRequestTest(NULL, &read_failure, true);
1536}
1537
1538TEST_P(HttpNetworkTransactionTest, SpdyPreconnectErrorAsyncEOF) {
1539  MockRead read_failure(ASYNC, OK);  // EOF
1540  PreconnectErrorResendRequestTest(NULL, &read_failure, true);
1541}
1542
1543TEST_P(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
1544  HttpRequestInfo request;
1545  request.method = "GET";
1546  request.url = GURL("http://www.google.com/");
1547  request.load_flags = 0;
1548
1549  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1550  scoped_ptr<HttpTransaction> trans(
1551      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1552
1553  MockRead data_reads[] = {
1554    MockRead(ASYNC, ERR_CONNECTION_RESET),
1555    MockRead("HTTP/1.0 200 OK\r\n\r\n"),  // Should not be used
1556    MockRead("hello world"),
1557    MockRead(SYNCHRONOUS, OK),
1558  };
1559  StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1560  session_deps_.socket_factory->AddSocketDataProvider(&data);
1561
1562  TestCompletionCallback callback;
1563
1564  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1565  EXPECT_EQ(ERR_IO_PENDING, rv);
1566
1567  rv = callback.WaitForResult();
1568  EXPECT_EQ(ERR_CONNECTION_RESET, rv);
1569
1570  const HttpResponseInfo* response = trans->GetResponseInfo();
1571  EXPECT_TRUE(response == NULL);
1572}
1573
1574// What do various browsers do when the server closes a non-keepalive
1575// connection without sending any response header or body?
1576//
1577// IE7: error page
1578// Safari 3.1.2 (Windows): error page
1579// Firefox 3.0.1: blank page
1580// Opera 9.52: after five attempts, blank page
1581// Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
1582// Us: error page (EMPTY_RESPONSE)
1583TEST_P(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
1584  MockRead data_reads[] = {
1585    MockRead(SYNCHRONOUS, OK),  // EOF
1586    MockRead("HTTP/1.0 200 OK\r\n\r\n"),  // Should not be used
1587    MockRead("hello world"),
1588    MockRead(SYNCHRONOUS, OK),
1589  };
1590  SimpleGetHelperResult out = SimpleGetHelper(data_reads,
1591                                              arraysize(data_reads));
1592  EXPECT_EQ(ERR_EMPTY_RESPONSE, out.rv);
1593}
1594
1595// Test that network access can be deferred and resumed.
1596TEST_P(HttpNetworkTransactionTest, ThrottleBeforeNetworkStart) {
1597  HttpRequestInfo request;
1598  request.method = "GET";
1599  request.url = GURL("http://www.google.com/");
1600  request.load_flags = 0;
1601
1602  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1603  scoped_ptr<HttpTransaction> trans(
1604      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1605
1606  // Defer on OnBeforeNetworkStart.
1607  BeforeNetworkStartHandler net_start_handler(true);  // defer
1608  trans->SetBeforeNetworkStartCallback(
1609      base::Bind(&BeforeNetworkStartHandler::OnBeforeNetworkStart,
1610                 base::Unretained(&net_start_handler)));
1611
1612  MockRead data_reads[] = {
1613    MockRead("HTTP/1.0 200 OK\r\n"),
1614    MockRead("Content-Length: 5\r\n\r\n"),
1615    MockRead("hello"),
1616    MockRead(SYNCHRONOUS, 0),
1617  };
1618  StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1619  session_deps_.socket_factory->AddSocketDataProvider(&data);
1620
1621  TestCompletionCallback callback;
1622
1623  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1624  EXPECT_EQ(ERR_IO_PENDING, rv);
1625  base::MessageLoop::current()->RunUntilIdle();
1626
1627  // Should have deferred for network start.
1628  EXPECT_TRUE(net_start_handler.observed_before_network_start());
1629  EXPECT_EQ(LOAD_STATE_WAITING_FOR_DELEGATE, trans->GetLoadState());
1630  EXPECT_TRUE(trans->GetResponseInfo() == NULL);
1631
1632  trans->ResumeNetworkStart();
1633  rv = callback.WaitForResult();
1634  EXPECT_EQ(OK, rv);
1635  EXPECT_TRUE(trans->GetResponseInfo() != NULL);
1636
1637  scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(100));
1638  rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
1639  if (rv == ERR_IO_PENDING)
1640    rv = callback.WaitForResult();
1641  EXPECT_EQ(5, rv);
1642  trans.reset();
1643}
1644
1645// Test that network use can be deferred and canceled.
1646TEST_P(HttpNetworkTransactionTest, ThrottleAndCancelBeforeNetworkStart) {
1647  HttpRequestInfo request;
1648  request.method = "GET";
1649  request.url = GURL("http://www.google.com/");
1650  request.load_flags = 0;
1651
1652  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1653  scoped_ptr<HttpTransaction> trans(
1654      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1655
1656  // Defer on OnBeforeNetworkStart.
1657  BeforeNetworkStartHandler net_start_handler(true);  // defer
1658  trans->SetBeforeNetworkStartCallback(
1659      base::Bind(&BeforeNetworkStartHandler::OnBeforeNetworkStart,
1660                 base::Unretained(&net_start_handler)));
1661
1662  TestCompletionCallback callback;
1663
1664  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1665  EXPECT_EQ(ERR_IO_PENDING, rv);
1666  base::MessageLoop::current()->RunUntilIdle();
1667
1668  // Should have deferred for network start.
1669  EXPECT_TRUE(net_start_handler.observed_before_network_start());
1670  EXPECT_EQ(LOAD_STATE_WAITING_FOR_DELEGATE, trans->GetLoadState());
1671  EXPECT_TRUE(trans->GetResponseInfo() == NULL);
1672}
1673
1674// Next 2 cases (KeepAliveEarlyClose and KeepAliveEarlyClose2) are regression
1675// tests. There was a bug causing HttpNetworkTransaction to hang in the
1676// destructor in such situations.
1677// See http://crbug.com/154712 and http://crbug.com/156609.
1678TEST_P(HttpNetworkTransactionTest, KeepAliveEarlyClose) {
1679  HttpRequestInfo request;
1680  request.method = "GET";
1681  request.url = GURL("http://www.google.com/");
1682  request.load_flags = 0;
1683
1684  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1685  scoped_ptr<HttpTransaction> trans(
1686      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1687
1688  MockRead data_reads[] = {
1689    MockRead("HTTP/1.0 200 OK\r\n"),
1690    MockRead("Connection: keep-alive\r\n"),
1691    MockRead("Content-Length: 100\r\n\r\n"),
1692    MockRead("hello"),
1693    MockRead(SYNCHRONOUS, 0),
1694  };
1695  StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1696  session_deps_.socket_factory->AddSocketDataProvider(&data);
1697
1698  TestCompletionCallback callback;
1699
1700  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1701  EXPECT_EQ(ERR_IO_PENDING, rv);
1702
1703  rv = callback.WaitForResult();
1704  EXPECT_EQ(OK, rv);
1705
1706  scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(100));
1707  rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
1708  if (rv == ERR_IO_PENDING)
1709    rv = callback.WaitForResult();
1710  EXPECT_EQ(5, rv);
1711  rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
1712  EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH, rv);
1713
1714  trans.reset();
1715  base::MessageLoop::current()->RunUntilIdle();
1716  EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
1717}
1718
1719TEST_P(HttpNetworkTransactionTest, KeepAliveEarlyClose2) {
1720  HttpRequestInfo request;
1721  request.method = "GET";
1722  request.url = GURL("http://www.google.com/");
1723  request.load_flags = 0;
1724
1725  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1726  scoped_ptr<HttpTransaction> trans(
1727      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1728
1729  MockRead data_reads[] = {
1730    MockRead("HTTP/1.0 200 OK\r\n"),
1731    MockRead("Connection: keep-alive\r\n"),
1732    MockRead("Content-Length: 100\r\n\r\n"),
1733    MockRead(SYNCHRONOUS, 0),
1734  };
1735  StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1736  session_deps_.socket_factory->AddSocketDataProvider(&data);
1737
1738  TestCompletionCallback callback;
1739
1740  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1741  EXPECT_EQ(ERR_IO_PENDING, rv);
1742
1743  rv = callback.WaitForResult();
1744  EXPECT_EQ(OK, rv);
1745
1746  scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(100));
1747  rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
1748  if (rv == ERR_IO_PENDING)
1749    rv = callback.WaitForResult();
1750  EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH, rv);
1751
1752  trans.reset();
1753  base::MessageLoop::current()->RunUntilIdle();
1754  EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
1755}
1756
1757// Test that we correctly reuse a keep-alive connection after not explicitly
1758// reading the body.
1759TEST_P(HttpNetworkTransactionTest, KeepAliveAfterUnreadBody) {
1760  HttpRequestInfo request;
1761  request.method = "GET";
1762  request.url = GURL("http://www.foo.com/");
1763  request.load_flags = 0;
1764
1765  CapturingNetLog net_log;
1766  session_deps_.net_log = &net_log;
1767  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1768
1769  // Note that because all these reads happen in the same
1770  // StaticSocketDataProvider, it shows that the same socket is being reused for
1771  // all transactions.
1772  MockRead data1_reads[] = {
1773    MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
1774    MockRead("HTTP/1.1 205 Reset Content\r\n\r\n"),
1775    MockRead("HTTP/1.1 304 Not Modified\r\n\r\n"),
1776    MockRead("HTTP/1.1 302 Found\r\n"
1777             "Content-Length: 0\r\n\r\n"),
1778    MockRead("HTTP/1.1 302 Found\r\n"
1779             "Content-Length: 5\r\n\r\n"
1780             "hello"),
1781    MockRead("HTTP/1.1 301 Moved Permanently\r\n"
1782             "Content-Length: 0\r\n\r\n"),
1783    MockRead("HTTP/1.1 301 Moved Permanently\r\n"
1784             "Content-Length: 5\r\n\r\n"
1785             "hello"),
1786    MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1787    MockRead("hello"),
1788  };
1789  StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), NULL, 0);
1790  session_deps_.socket_factory->AddSocketDataProvider(&data1);
1791
1792  MockRead data2_reads[] = {
1793    MockRead(SYNCHRONOUS, ERR_UNEXPECTED),  // Should not be reached.
1794  };
1795  StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
1796  session_deps_.socket_factory->AddSocketDataProvider(&data2);
1797
1798  const int kNumUnreadBodies = arraysize(data1_reads) - 2;
1799  std::string response_lines[kNumUnreadBodies];
1800
1801  uint32 first_socket_log_id = NetLog::Source::kInvalidId;
1802  for (size_t i = 0; i < arraysize(data1_reads) - 2; ++i) {
1803    TestCompletionCallback callback;
1804
1805    scoped_ptr<HttpTransaction> trans(
1806        new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1807
1808    int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1809    EXPECT_EQ(ERR_IO_PENDING, rv);
1810
1811    rv = callback.WaitForResult();
1812    EXPECT_EQ(OK, rv);
1813
1814    LoadTimingInfo load_timing_info;
1815    EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
1816    if (i == 0) {
1817      TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
1818      first_socket_log_id = load_timing_info.socket_log_id;
1819    } else {
1820      TestLoadTimingReused(load_timing_info);
1821      EXPECT_EQ(first_socket_log_id, load_timing_info.socket_log_id);
1822    }
1823
1824    const HttpResponseInfo* response = trans->GetResponseInfo();
1825    ASSERT_TRUE(response != NULL);
1826
1827    ASSERT_TRUE(response->headers.get() != NULL);
1828    response_lines[i] = response->headers->GetStatusLine();
1829
1830    // We intentionally don't read the response bodies.
1831  }
1832
1833  const char* const kStatusLines[] = {
1834    "HTTP/1.1 204 No Content",
1835    "HTTP/1.1 205 Reset Content",
1836    "HTTP/1.1 304 Not Modified",
1837    "HTTP/1.1 302 Found",
1838    "HTTP/1.1 302 Found",
1839    "HTTP/1.1 301 Moved Permanently",
1840    "HTTP/1.1 301 Moved Permanently",
1841  };
1842
1843  COMPILE_ASSERT(kNumUnreadBodies == arraysize(kStatusLines),
1844                 forgot_to_update_kStatusLines);
1845
1846  for (int i = 0; i < kNumUnreadBodies; ++i)
1847    EXPECT_EQ(kStatusLines[i], response_lines[i]);
1848
1849  TestCompletionCallback callback;
1850  scoped_ptr<HttpTransaction> trans(
1851      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1852  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1853  EXPECT_EQ(ERR_IO_PENDING, rv);
1854  rv = callback.WaitForResult();
1855  EXPECT_EQ(OK, rv);
1856  const HttpResponseInfo* response = trans->GetResponseInfo();
1857  ASSERT_TRUE(response != NULL);
1858  ASSERT_TRUE(response->headers.get() != NULL);
1859  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1860  std::string response_data;
1861  rv = ReadTransaction(trans.get(), &response_data);
1862  EXPECT_EQ(OK, rv);
1863  EXPECT_EQ("hello", response_data);
1864}
1865
1866// Test the request-challenge-retry sequence for basic auth.
1867// (basic auth is the easiest to mock, because it has no randomness).
1868TEST_P(HttpNetworkTransactionTest, BasicAuth) {
1869  HttpRequestInfo request;
1870  request.method = "GET";
1871  request.url = GURL("http://www.google.com/");
1872  request.load_flags = 0;
1873
1874  CapturingNetLog log;
1875  session_deps_.net_log = &log;
1876  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1877  scoped_ptr<HttpTransaction> trans(
1878      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1879
1880  MockWrite data_writes1[] = {
1881    MockWrite("GET / HTTP/1.1\r\n"
1882              "Host: www.google.com\r\n"
1883              "Connection: keep-alive\r\n\r\n"),
1884  };
1885
1886  MockRead data_reads1[] = {
1887    MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1888    // Give a couple authenticate options (only the middle one is actually
1889    // supported).
1890    MockRead("WWW-Authenticate: Basic invalid\r\n"),  // Malformed.
1891    MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1892    MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
1893    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1894    // Large content-length -- won't matter, as connection will be reset.
1895    MockRead("Content-Length: 10000\r\n\r\n"),
1896    MockRead(SYNCHRONOUS, ERR_FAILED),
1897  };
1898
1899  // After calling trans->RestartWithAuth(), this is the request we should
1900  // be issuing -- the final header line contains the credentials.
1901  MockWrite data_writes2[] = {
1902    MockWrite("GET / HTTP/1.1\r\n"
1903              "Host: www.google.com\r\n"
1904              "Connection: keep-alive\r\n"
1905              "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1906  };
1907
1908  // Lastly, the server responds with the actual content.
1909  MockRead data_reads2[] = {
1910    MockRead("HTTP/1.0 200 OK\r\n"),
1911    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1912    MockRead("Content-Length: 100\r\n\r\n"),
1913    MockRead(SYNCHRONOUS, OK),
1914  };
1915
1916  StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1917                                 data_writes1, arraysize(data_writes1));
1918  StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1919                                 data_writes2, arraysize(data_writes2));
1920  session_deps_.socket_factory->AddSocketDataProvider(&data1);
1921  session_deps_.socket_factory->AddSocketDataProvider(&data2);
1922
1923  TestCompletionCallback callback1;
1924
1925  int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
1926  EXPECT_EQ(ERR_IO_PENDING, rv);
1927
1928  rv = callback1.WaitForResult();
1929  EXPECT_EQ(OK, rv);
1930
1931  LoadTimingInfo load_timing_info1;
1932  EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info1));
1933  TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
1934
1935  int64 reads_size1 = ReadsSize(data_reads1, arraysize(data_reads1));
1936  EXPECT_EQ(reads_size1, trans->GetTotalReceivedBytes());
1937
1938  const HttpResponseInfo* response = trans->GetResponseInfo();
1939  ASSERT_TRUE(response != NULL);
1940  EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
1941
1942  TestCompletionCallback callback2;
1943
1944  rv = trans->RestartWithAuth(
1945      AuthCredentials(kFoo, kBar), callback2.callback());
1946  EXPECT_EQ(ERR_IO_PENDING, rv);
1947
1948  rv = callback2.WaitForResult();
1949  EXPECT_EQ(OK, rv);
1950
1951  LoadTimingInfo load_timing_info2;
1952  EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info2));
1953  TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_DNS_TIMES);
1954  // The load timing after restart should have a new socket ID, and times after
1955  // those of the first load timing.
1956  EXPECT_LE(load_timing_info1.receive_headers_end,
1957            load_timing_info2.connect_timing.connect_start);
1958  EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
1959
1960  int64 reads_size2 = ReadsSize(data_reads2, arraysize(data_reads2));
1961  EXPECT_EQ(reads_size1 + reads_size2, trans->GetTotalReceivedBytes());
1962
1963  response = trans->GetResponseInfo();
1964  ASSERT_TRUE(response != NULL);
1965  EXPECT_TRUE(response->auth_challenge.get() == NULL);
1966  EXPECT_EQ(100, response->headers->GetContentLength());
1967}
1968
1969TEST_P(HttpNetworkTransactionTest, DoNotSendAuth) {
1970  HttpRequestInfo request;
1971  request.method = "GET";
1972  request.url = GURL("http://www.google.com/");
1973  request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
1974
1975  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1976  scoped_ptr<HttpTransaction> trans(
1977      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1978
1979  MockWrite data_writes[] = {
1980    MockWrite("GET / HTTP/1.1\r\n"
1981              "Host: www.google.com\r\n"
1982              "Connection: keep-alive\r\n\r\n"),
1983  };
1984
1985  MockRead data_reads[] = {
1986    MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1987    MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1988    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1989    // Large content-length -- won't matter, as connection will be reset.
1990    MockRead("Content-Length: 10000\r\n\r\n"),
1991    MockRead(SYNCHRONOUS, ERR_FAILED),
1992  };
1993
1994  StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1995                                data_writes, arraysize(data_writes));
1996  session_deps_.socket_factory->AddSocketDataProvider(&data);
1997  TestCompletionCallback callback;
1998
1999  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
2000  EXPECT_EQ(ERR_IO_PENDING, rv);
2001
2002  rv = callback.WaitForResult();
2003  EXPECT_EQ(0, rv);
2004
2005  int64 reads_size = ReadsSize(data_reads, arraysize(data_reads));
2006  EXPECT_EQ(reads_size, trans->GetTotalReceivedBytes());
2007
2008  const HttpResponseInfo* response = trans->GetResponseInfo();
2009  ASSERT_TRUE(response != NULL);
2010  EXPECT_TRUE(response->auth_challenge.get() == NULL);
2011}
2012
2013// Test the request-challenge-retry sequence for basic auth, over a keep-alive
2014// connection.
2015TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
2016  HttpRequestInfo request;
2017  request.method = "GET";
2018  request.url = GURL("http://www.google.com/");
2019  request.load_flags = 0;
2020
2021  CapturingNetLog log;
2022  session_deps_.net_log = &log;
2023  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2024
2025  MockWrite data_writes1[] = {
2026    MockWrite("GET / HTTP/1.1\r\n"
2027              "Host: www.google.com\r\n"
2028              "Connection: keep-alive\r\n\r\n"),
2029
2030    // After calling trans->RestartWithAuth(), this is the request we should
2031    // be issuing -- the final header line contains the credentials.
2032    MockWrite("GET / HTTP/1.1\r\n"
2033              "Host: www.google.com\r\n"
2034              "Connection: keep-alive\r\n"
2035              "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2036  };
2037
2038  MockRead data_reads1[] = {
2039    MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2040    MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2041    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2042    MockRead("Content-Length: 14\r\n\r\n"),
2043    MockRead("Unauthorized\r\n"),
2044
2045    // Lastly, the server responds with the actual content.
2046    MockRead("HTTP/1.1 200 OK\r\n"),
2047    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2048    MockRead("Content-Length: 5\r\n\r\n"),
2049    MockRead("Hello"),
2050  };
2051
2052  // If there is a regression where we disconnect a Keep-Alive
2053  // connection during an auth roundtrip, we'll end up reading this.
2054  MockRead data_reads2[] = {
2055    MockRead(SYNCHRONOUS, ERR_FAILED),
2056  };
2057
2058  StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2059                                 data_writes1, arraysize(data_writes1));
2060  StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2061                                 NULL, 0);
2062  session_deps_.socket_factory->AddSocketDataProvider(&data1);
2063  session_deps_.socket_factory->AddSocketDataProvider(&data2);
2064
2065  TestCompletionCallback callback1;
2066
2067  scoped_ptr<HttpTransaction> trans(
2068      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2069  int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
2070  EXPECT_EQ(ERR_IO_PENDING, rv);
2071
2072  rv = callback1.WaitForResult();
2073  EXPECT_EQ(OK, rv);
2074
2075  LoadTimingInfo load_timing_info1;
2076  EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info1));
2077  TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
2078
2079  const HttpResponseInfo* response = trans->GetResponseInfo();
2080  ASSERT_TRUE(response != NULL);
2081  EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
2082
2083  TestCompletionCallback callback2;
2084
2085  rv = trans->RestartWithAuth(
2086      AuthCredentials(kFoo, kBar), callback2.callback());
2087  EXPECT_EQ(ERR_IO_PENDING, rv);
2088
2089  rv = callback2.WaitForResult();
2090  EXPECT_EQ(OK, rv);
2091
2092  LoadTimingInfo load_timing_info2;
2093  EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info2));
2094  TestLoadTimingReused(load_timing_info2);
2095  // The load timing after restart should have the same socket ID, and times
2096  // those of the first load timing.
2097  EXPECT_LE(load_timing_info1.receive_headers_end,
2098            load_timing_info2.send_start);
2099  EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
2100
2101  response = trans->GetResponseInfo();
2102  ASSERT_TRUE(response != NULL);
2103  EXPECT_TRUE(response->auth_challenge.get() == NULL);
2104  EXPECT_EQ(5, response->headers->GetContentLength());
2105
2106  std::string response_data;
2107  rv = ReadTransaction(trans.get(), &response_data);
2108  EXPECT_EQ(OK, rv);
2109  int64 reads_size1 = ReadsSize(data_reads1, arraysize(data_reads1));
2110  EXPECT_EQ(reads_size1, trans->GetTotalReceivedBytes());
2111}
2112
2113// Test the request-challenge-retry sequence for basic auth, over a keep-alive
2114// connection and with no response body to drain.
2115TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
2116  HttpRequestInfo request;
2117  request.method = "GET";
2118  request.url = GURL("http://www.google.com/");
2119  request.load_flags = 0;
2120
2121  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2122
2123  MockWrite data_writes1[] = {
2124    MockWrite("GET / HTTP/1.1\r\n"
2125              "Host: www.google.com\r\n"
2126              "Connection: keep-alive\r\n\r\n"),
2127
2128    // After calling trans->RestartWithAuth(), this is the request we should
2129    // be issuing -- the final header line contains the credentials.
2130    MockWrite("GET / HTTP/1.1\r\n"
2131              "Host: www.google.com\r\n"
2132              "Connection: keep-alive\r\n"
2133              "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2134  };
2135
2136  MockRead data_reads1[] = {
2137    MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2138    MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2139    MockRead("Content-Length: 0\r\n\r\n"),  // No response body.
2140
2141    // Lastly, the server responds with the actual content.
2142    MockRead("HTTP/1.1 200 OK\r\n"),
2143    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2144    MockRead("Content-Length: 5\r\n\r\n"),
2145    MockRead("hello"),
2146  };
2147
2148  // An incorrect reconnect would cause this to be read.
2149  MockRead data_reads2[] = {
2150    MockRead(SYNCHRONOUS, ERR_FAILED),
2151  };
2152
2153  StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2154                                 data_writes1, arraysize(data_writes1));
2155  StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2156                                 NULL, 0);
2157  session_deps_.socket_factory->AddSocketDataProvider(&data1);
2158  session_deps_.socket_factory->AddSocketDataProvider(&data2);
2159
2160  TestCompletionCallback callback1;
2161
2162  scoped_ptr<HttpTransaction> trans(
2163      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2164  int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
2165  EXPECT_EQ(ERR_IO_PENDING, rv);
2166
2167  rv = callback1.WaitForResult();
2168  EXPECT_EQ(OK, rv);
2169
2170  const HttpResponseInfo* response = trans->GetResponseInfo();
2171  ASSERT_TRUE(response != NULL);
2172  EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
2173
2174  TestCompletionCallback callback2;
2175
2176  rv = trans->RestartWithAuth(
2177      AuthCredentials(kFoo, kBar), callback2.callback());
2178  EXPECT_EQ(ERR_IO_PENDING, rv);
2179
2180  rv = callback2.WaitForResult();
2181  EXPECT_EQ(OK, rv);
2182
2183  response = trans->GetResponseInfo();
2184  ASSERT_TRUE(response != NULL);
2185  EXPECT_TRUE(response->auth_challenge.get() == NULL);
2186  EXPECT_EQ(5, response->headers->GetContentLength());
2187}
2188
2189// Test the request-challenge-retry sequence for basic auth, over a keep-alive
2190// connection and with a large response body to drain.
2191TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
2192  HttpRequestInfo request;
2193  request.method = "GET";
2194  request.url = GURL("http://www.google.com/");
2195  request.load_flags = 0;
2196
2197  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2198
2199  MockWrite data_writes1[] = {
2200    MockWrite("GET / HTTP/1.1\r\n"
2201              "Host: www.google.com\r\n"
2202              "Connection: keep-alive\r\n\r\n"),
2203
2204    // After calling trans->RestartWithAuth(), this is the request we should
2205    // be issuing -- the final header line contains the credentials.
2206    MockWrite("GET / HTTP/1.1\r\n"
2207              "Host: www.google.com\r\n"
2208              "Connection: keep-alive\r\n"
2209              "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2210  };
2211
2212  // Respond with 5 kb of response body.
2213  std::string large_body_string("Unauthorized");
2214  large_body_string.append(5 * 1024, ' ');
2215  large_body_string.append("\r\n");
2216
2217  MockRead data_reads1[] = {
2218    MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2219    MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2220    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2221    // 5134 = 12 + 5 * 1024 + 2
2222    MockRead("Content-Length: 5134\r\n\r\n"),
2223    MockRead(ASYNC, large_body_string.data(), large_body_string.size()),
2224
2225    // Lastly, the server responds with the actual content.
2226    MockRead("HTTP/1.1 200 OK\r\n"),
2227    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2228    MockRead("Content-Length: 5\r\n\r\n"),
2229    MockRead("hello"),
2230  };
2231
2232  // An incorrect reconnect would cause this to be read.
2233  MockRead data_reads2[] = {
2234    MockRead(SYNCHRONOUS, ERR_FAILED),
2235  };
2236
2237  StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2238                                 data_writes1, arraysize(data_writes1));
2239  StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2240                                 NULL, 0);
2241  session_deps_.socket_factory->AddSocketDataProvider(&data1);
2242  session_deps_.socket_factory->AddSocketDataProvider(&data2);
2243
2244  TestCompletionCallback callback1;
2245
2246  scoped_ptr<HttpTransaction> trans(
2247      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2248  int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
2249  EXPECT_EQ(ERR_IO_PENDING, rv);
2250
2251  rv = callback1.WaitForResult();
2252  EXPECT_EQ(OK, rv);
2253
2254  const HttpResponseInfo* response = trans->GetResponseInfo();
2255  ASSERT_TRUE(response != NULL);
2256  EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
2257
2258  TestCompletionCallback callback2;
2259
2260  rv = trans->RestartWithAuth(
2261      AuthCredentials(kFoo, kBar), callback2.callback());
2262  EXPECT_EQ(ERR_IO_PENDING, rv);
2263
2264  rv = callback2.WaitForResult();
2265  EXPECT_EQ(OK, rv);
2266
2267  response = trans->GetResponseInfo();
2268  ASSERT_TRUE(response != NULL);
2269  EXPECT_TRUE(response->auth_challenge.get() == NULL);
2270  EXPECT_EQ(5, response->headers->GetContentLength());
2271}
2272
2273// Test the request-challenge-retry sequence for basic auth, over a keep-alive
2274// connection, but the server gets impatient and closes the connection.
2275TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) {
2276  HttpRequestInfo request;
2277  request.method = "GET";
2278  request.url = GURL("http://www.google.com/");
2279  request.load_flags = 0;
2280
2281  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2282
2283  MockWrite data_writes1[] = {
2284    MockWrite("GET / HTTP/1.1\r\n"
2285              "Host: www.google.com\r\n"
2286              "Connection: keep-alive\r\n\r\n"),
2287    // This simulates the seemingly successful write to a closed connection
2288    // if the bug is not fixed.
2289    MockWrite("GET / HTTP/1.1\r\n"
2290              "Host: www.google.com\r\n"
2291              "Connection: keep-alive\r\n"
2292              "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2293  };
2294
2295  MockRead data_reads1[] = {
2296    MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2297    MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2298    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2299    MockRead("Content-Length: 14\r\n\r\n"),
2300    // Tell MockTCPClientSocket to simulate the server closing the connection.
2301    MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
2302    MockRead("Unauthorized\r\n"),
2303    MockRead(SYNCHRONOUS, OK),  // The server closes the connection.
2304  };
2305
2306  // After calling trans->RestartWithAuth(), this is the request we should
2307  // be issuing -- the final header line contains the credentials.
2308  MockWrite data_writes2[] = {
2309    MockWrite("GET / HTTP/1.1\r\n"
2310              "Host: www.google.com\r\n"
2311              "Connection: keep-alive\r\n"
2312              "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2313  };
2314
2315  // Lastly, the server responds with the actual content.
2316  MockRead data_reads2[] = {
2317    MockRead("HTTP/1.1 200 OK\r\n"),
2318    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2319    MockRead("Content-Length: 5\r\n\r\n"),
2320    MockRead("hello"),
2321  };
2322
2323  StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2324                                 data_writes1, arraysize(data_writes1));
2325  StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2326                                 data_writes2, arraysize(data_writes2));
2327  session_deps_.socket_factory->AddSocketDataProvider(&data1);
2328  session_deps_.socket_factory->AddSocketDataProvider(&data2);
2329
2330  TestCompletionCallback callback1;
2331
2332  scoped_ptr<HttpTransaction> trans(
2333      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2334  int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
2335  EXPECT_EQ(ERR_IO_PENDING, rv);
2336
2337  rv = callback1.WaitForResult();
2338  EXPECT_EQ(OK, rv);
2339
2340  const HttpResponseInfo* response = trans->GetResponseInfo();
2341  ASSERT_TRUE(response != NULL);
2342  EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
2343
2344  TestCompletionCallback callback2;
2345
2346  rv = trans->RestartWithAuth(
2347      AuthCredentials(kFoo, kBar), callback2.callback());
2348  EXPECT_EQ(ERR_IO_PENDING, rv);
2349
2350  rv = callback2.WaitForResult();
2351  EXPECT_EQ(OK, rv);
2352
2353  response = trans->GetResponseInfo();
2354  ASSERT_TRUE(response != NULL);
2355  EXPECT_TRUE(response->auth_challenge.get() == NULL);
2356  EXPECT_EQ(5, response->headers->GetContentLength());
2357}
2358
2359// Test the request-challenge-retry sequence for basic auth, over a connection
2360// that requires a restart when setting up an SSL tunnel.
2361TEST_P(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAlive) {
2362  HttpRequestInfo request;
2363  request.method = "GET";
2364  request.url = GURL("https://www.google.com/");
2365  // when the no authentication data flag is set.
2366  request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
2367
2368  // Configure against proxy server "myproxy:70".
2369  session_deps_.proxy_service.reset(
2370      ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
2371  CapturingBoundNetLog log;
2372  session_deps_.net_log = log.bound().net_log();
2373  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2374
2375  // Since we have proxy, should try to establish tunnel.
2376  MockWrite data_writes1[] = {
2377    MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2378              "Host: www.google.com\r\n"
2379              "Proxy-Connection: keep-alive\r\n\r\n"),
2380
2381    // After calling trans->RestartWithAuth(), this is the request we should
2382    // be issuing -- the final header line contains the credentials.
2383    MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2384              "Host: www.google.com\r\n"
2385              "Proxy-Connection: keep-alive\r\n"
2386              "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2387
2388    MockWrite("GET / HTTP/1.1\r\n"
2389              "Host: www.google.com\r\n"
2390              "Connection: keep-alive\r\n\r\n"),
2391  };
2392
2393  // The proxy responds to the connect with a 407, using a persistent
2394  // connection.
2395  MockRead data_reads1[] = {
2396    // No credentials.
2397    MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2398    MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2399    MockRead("Proxy-Connection: close\r\n\r\n"),
2400
2401    MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2402
2403    MockRead("HTTP/1.1 200 OK\r\n"),
2404    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2405    MockRead("Content-Length: 5\r\n\r\n"),
2406    MockRead(SYNCHRONOUS, "hello"),
2407  };
2408
2409  StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2410                                 data_writes1, arraysize(data_writes1));
2411  session_deps_.socket_factory->AddSocketDataProvider(&data1);
2412  SSLSocketDataProvider ssl(ASYNC, OK);
2413  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2414
2415  TestCompletionCallback callback1;
2416
2417  scoped_ptr<HttpTransaction> trans(
2418      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2419
2420  int rv = trans->Start(&request, callback1.callback(), log.bound());
2421  EXPECT_EQ(ERR_IO_PENDING, rv);
2422
2423  rv = callback1.WaitForResult();
2424  EXPECT_EQ(OK, rv);
2425  net::CapturingNetLog::CapturedEntryList entries;
2426  log.GetEntries(&entries);
2427  size_t pos = ExpectLogContainsSomewhere(
2428      entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
2429      NetLog::PHASE_NONE);
2430  ExpectLogContainsSomewhere(
2431      entries, pos,
2432      NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
2433      NetLog::PHASE_NONE);
2434
2435  const HttpResponseInfo* response = trans->GetResponseInfo();
2436  ASSERT_TRUE(response != NULL);
2437  ASSERT_FALSE(response->headers.get() == NULL);
2438  EXPECT_EQ(407, response->headers->response_code());
2439  EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2440  EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2441
2442  LoadTimingInfo load_timing_info;
2443  // CONNECT requests and responses are handled at the connect job level, so
2444  // the transaction does not yet have a connection.
2445  EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
2446
2447  TestCompletionCallback callback2;
2448
2449  rv = trans->RestartWithAuth(
2450      AuthCredentials(kFoo, kBar), callback2.callback());
2451  EXPECT_EQ(ERR_IO_PENDING, rv);
2452
2453  rv = callback2.WaitForResult();
2454  EXPECT_EQ(OK, rv);
2455
2456  response = trans->GetResponseInfo();
2457  ASSERT_TRUE(response != NULL);
2458
2459  EXPECT_TRUE(response->headers->IsKeepAlive());
2460  EXPECT_EQ(200, response->headers->response_code());
2461  EXPECT_EQ(5, response->headers->GetContentLength());
2462  EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2463
2464  // The password prompt info should not be set.
2465  EXPECT_TRUE(response->auth_challenge.get() == NULL);
2466
2467  EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
2468  TestLoadTimingNotReusedWithPac(load_timing_info,
2469                                 CONNECT_TIMING_HAS_SSL_TIMES);
2470
2471  trans.reset();
2472  session->CloseAllConnections();
2473}
2474
2475// Test the request-challenge-retry sequence for basic auth, over a keep-alive
2476// proxy connection, when setting up an SSL tunnel.
2477TEST_P(HttpNetworkTransactionTest, BasicAuthProxyKeepAlive) {
2478  HttpRequestInfo request;
2479  request.method = "GET";
2480  request.url = GURL("https://www.google.com/");
2481  // Ensure that proxy authentication is attempted even
2482  // when the no authentication data flag is set.
2483  request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
2484
2485  // Configure against proxy server "myproxy:70".
2486  session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
2487  CapturingBoundNetLog log;
2488  session_deps_.net_log = log.bound().net_log();
2489  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2490
2491  scoped_ptr<HttpTransaction> trans(
2492      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2493
2494  // Since we have proxy, should try to establish tunnel.
2495  MockWrite data_writes1[] = {
2496    MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2497              "Host: www.google.com\r\n"
2498              "Proxy-Connection: keep-alive\r\n\r\n"),
2499
2500    // After calling trans->RestartWithAuth(), this is the request we should
2501    // be issuing -- the final header line contains the credentials.
2502    MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2503              "Host: www.google.com\r\n"
2504              "Proxy-Connection: keep-alive\r\n"
2505              "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
2506  };
2507
2508  // The proxy responds to the connect with a 407, using a persistent
2509  // connection.
2510  MockRead data_reads1[] = {
2511    // No credentials.
2512    MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2513    MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2514    MockRead("Content-Length: 10\r\n\r\n"),
2515    MockRead("0123456789"),
2516
2517    // Wrong credentials (wrong password).
2518    MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2519    MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2520    MockRead("Content-Length: 10\r\n\r\n"),
2521    // No response body because the test stops reading here.
2522    MockRead(SYNCHRONOUS, ERR_UNEXPECTED),  // Should not be reached.
2523  };
2524
2525  StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2526                                 data_writes1, arraysize(data_writes1));
2527  session_deps_.socket_factory->AddSocketDataProvider(&data1);
2528
2529  TestCompletionCallback callback1;
2530
2531  int rv = trans->Start(&request, callback1.callback(), log.bound());
2532  EXPECT_EQ(ERR_IO_PENDING, rv);
2533
2534  rv = callback1.WaitForResult();
2535  EXPECT_EQ(OK, rv);
2536  net::CapturingNetLog::CapturedEntryList entries;
2537  log.GetEntries(&entries);
2538  size_t pos = ExpectLogContainsSomewhere(
2539      entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
2540      NetLog::PHASE_NONE);
2541  ExpectLogContainsSomewhere(
2542      entries, pos,
2543      NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
2544      NetLog::PHASE_NONE);
2545
2546  const HttpResponseInfo* response = trans->GetResponseInfo();
2547  ASSERT_TRUE(response != NULL);
2548  ASSERT_FALSE(response->headers.get() == NULL);
2549  EXPECT_TRUE(response->headers->IsKeepAlive());
2550  EXPECT_EQ(407, response->headers->response_code());
2551  EXPECT_EQ(10, response->headers->GetContentLength());
2552  EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2553  EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2554
2555  TestCompletionCallback callback2;
2556
2557  // Wrong password (should be "bar").
2558  rv = trans->RestartWithAuth(
2559      AuthCredentials(kFoo, kBaz), callback2.callback());
2560  EXPECT_EQ(ERR_IO_PENDING, rv);
2561
2562  rv = callback2.WaitForResult();
2563  EXPECT_EQ(OK, rv);
2564
2565  response = trans->GetResponseInfo();
2566  ASSERT_TRUE(response != NULL);
2567  ASSERT_FALSE(response->headers.get() == NULL);
2568  EXPECT_TRUE(response->headers->IsKeepAlive());
2569  EXPECT_EQ(407, response->headers->response_code());
2570  EXPECT_EQ(10, response->headers->GetContentLength());
2571  EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2572  EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2573
2574  // Flush the idle socket before the NetLog and HttpNetworkTransaction go
2575  // out of scope.
2576  session->CloseAllConnections();
2577}
2578
2579// Test that we don't read the response body when we fail to establish a tunnel,
2580// even if the user cancels the proxy's auth attempt.
2581TEST_P(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
2582  HttpRequestInfo request;
2583  request.method = "GET";
2584  request.url = GURL("https://www.google.com/");
2585  request.load_flags = 0;
2586
2587  // Configure against proxy server "myproxy:70".
2588  session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
2589
2590  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2591
2592  scoped_ptr<HttpTransaction> trans(
2593      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2594
2595  // Since we have proxy, should try to establish tunnel.
2596  MockWrite data_writes[] = {
2597    MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2598              "Host: www.google.com\r\n"
2599              "Proxy-Connection: keep-alive\r\n\r\n"),
2600  };
2601
2602  // The proxy responds to the connect with a 407.
2603  MockRead data_reads[] = {
2604    MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2605    MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2606    MockRead("Content-Length: 10\r\n\r\n"),
2607    MockRead(SYNCHRONOUS, ERR_UNEXPECTED),  // Should not be reached.
2608  };
2609
2610  StaticSocketDataProvider data(data_reads, arraysize(data_reads),
2611                                data_writes, arraysize(data_writes));
2612  session_deps_.socket_factory->AddSocketDataProvider(&data);
2613
2614  TestCompletionCallback callback;
2615
2616  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
2617  EXPECT_EQ(ERR_IO_PENDING, rv);
2618
2619  rv = callback.WaitForResult();
2620  EXPECT_EQ(OK, rv);
2621
2622  const HttpResponseInfo* response = trans->GetResponseInfo();
2623  ASSERT_TRUE(response != NULL);
2624
2625  EXPECT_TRUE(response->headers->IsKeepAlive());
2626  EXPECT_EQ(407, response->headers->response_code());
2627  EXPECT_EQ(10, response->headers->GetContentLength());
2628  EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2629
2630  std::string response_data;
2631  rv = ReadTransaction(trans.get(), &response_data);
2632  EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
2633
2634  // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
2635  session->CloseAllConnections();
2636}
2637
2638// Test when a server (non-proxy) returns a 407 (proxy-authenticate).
2639// The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
2640TEST_P(HttpNetworkTransactionTest, UnexpectedProxyAuth) {
2641  HttpRequestInfo request;
2642  request.method = "GET";
2643  request.url = GURL("http://www.google.com/");
2644  request.load_flags = 0;
2645
2646  // We are using a DIRECT connection (i.e. no proxy) for this session.
2647  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2648  scoped_ptr<HttpTransaction> trans(
2649      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2650
2651  MockWrite data_writes1[] = {
2652    MockWrite("GET / HTTP/1.1\r\n"
2653              "Host: www.google.com\r\n"
2654              "Connection: keep-alive\r\n\r\n"),
2655  };
2656
2657  MockRead data_reads1[] = {
2658    MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
2659    MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2660    // Large content-length -- won't matter, as connection will be reset.
2661    MockRead("Content-Length: 10000\r\n\r\n"),
2662    MockRead(SYNCHRONOUS, ERR_FAILED),
2663  };
2664
2665  StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2666                                 data_writes1, arraysize(data_writes1));
2667  session_deps_.socket_factory->AddSocketDataProvider(&data1);
2668
2669  TestCompletionCallback callback;
2670
2671  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
2672  EXPECT_EQ(ERR_IO_PENDING, rv);
2673
2674  rv = callback.WaitForResult();
2675  EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
2676}
2677
2678// Tests when an HTTPS server (non-proxy) returns a 407 (proxy-authentication)
2679// through a non-authenticating proxy. The request should fail with
2680// ERR_UNEXPECTED_PROXY_AUTH.
2681// Note that it is impossible to detect if an HTTP server returns a 407 through
2682// a non-authenticating proxy - there is nothing to indicate whether the
2683// response came from the proxy or the server, so it is treated as if the proxy
2684// issued the challenge.
2685TEST_P(HttpNetworkTransactionTest,
2686       HttpsServerRequestsProxyAuthThroughProxy) {
2687  HttpRequestInfo request;
2688  request.method = "GET";
2689  request.url = GURL("https://www.google.com/");
2690
2691  session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
2692  CapturingBoundNetLog log;
2693  session_deps_.net_log = log.bound().net_log();
2694  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2695
2696  // Since we have proxy, should try to establish tunnel.
2697  MockWrite data_writes1[] = {
2698    MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2699              "Host: www.google.com\r\n"
2700              "Proxy-Connection: keep-alive\r\n\r\n"),
2701
2702    MockWrite("GET / HTTP/1.1\r\n"
2703              "Host: www.google.com\r\n"
2704              "Connection: keep-alive\r\n\r\n"),
2705  };
2706
2707  MockRead data_reads1[] = {
2708    MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2709
2710    MockRead("HTTP/1.1 407 Unauthorized\r\n"),
2711    MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2712    MockRead("\r\n"),
2713    MockRead(SYNCHRONOUS, OK),
2714  };
2715
2716  StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2717                                 data_writes1, arraysize(data_writes1));
2718  session_deps_.socket_factory->AddSocketDataProvider(&data1);
2719  SSLSocketDataProvider ssl(ASYNC, OK);
2720  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2721
2722  TestCompletionCallback callback1;
2723
2724  scoped_ptr<HttpTransaction> trans(
2725      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2726
2727  int rv = trans->Start(&request, callback1.callback(), log.bound());
2728  EXPECT_EQ(ERR_IO_PENDING, rv);
2729
2730  rv = callback1.WaitForResult();
2731  EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
2732  net::CapturingNetLog::CapturedEntryList entries;
2733  log.GetEntries(&entries);
2734  size_t pos = ExpectLogContainsSomewhere(
2735      entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
2736      NetLog::PHASE_NONE);
2737  ExpectLogContainsSomewhere(
2738      entries, pos,
2739      NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
2740      NetLog::PHASE_NONE);
2741}
2742
2743// Test the load timing for HTTPS requests with an HTTP proxy.
2744TEST_P(HttpNetworkTransactionTest, HttpProxyLoadTimingNoPacTwoRequests) {
2745  HttpRequestInfo request1;
2746  request1.method = "GET";
2747  request1.url = GURL("https://www.google.com/1");
2748
2749  HttpRequestInfo request2;
2750  request2.method = "GET";
2751  request2.url = GURL("https://www.google.com/2");
2752
2753  // Configure against proxy server "myproxy:70".
2754  session_deps_.proxy_service.reset(
2755      ProxyService::CreateFixed("PROXY myproxy:70"));
2756  CapturingBoundNetLog log;
2757  session_deps_.net_log = log.bound().net_log();
2758  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2759
2760  // Since we have proxy, should try to establish tunnel.
2761  MockWrite data_writes1[] = {
2762    MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2763              "Host: www.google.com\r\n"
2764              "Proxy-Connection: keep-alive\r\n\r\n"),
2765
2766    MockWrite("GET /1 HTTP/1.1\r\n"
2767              "Host: www.google.com\r\n"
2768              "Connection: keep-alive\r\n\r\n"),
2769
2770    MockWrite("GET /2 HTTP/1.1\r\n"
2771              "Host: www.google.com\r\n"
2772              "Connection: keep-alive\r\n\r\n"),
2773  };
2774
2775  // The proxy responds to the connect with a 407, using a persistent
2776  // connection.
2777  MockRead data_reads1[] = {
2778    MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2779
2780    MockRead("HTTP/1.1 200 OK\r\n"),
2781    MockRead("Content-Length: 1\r\n\r\n"),
2782    MockRead(SYNCHRONOUS, "1"),
2783
2784    MockRead("HTTP/1.1 200 OK\r\n"),
2785    MockRead("Content-Length: 2\r\n\r\n"),
2786    MockRead(SYNCHRONOUS, "22"),
2787  };
2788
2789  StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2790                                 data_writes1, arraysize(data_writes1));
2791  session_deps_.socket_factory->AddSocketDataProvider(&data1);
2792  SSLSocketDataProvider ssl(ASYNC, OK);
2793  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2794
2795  TestCompletionCallback callback1;
2796  scoped_ptr<HttpTransaction> trans1(
2797      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2798
2799  int rv = trans1->Start(&request1, callback1.callback(), log.bound());
2800  EXPECT_EQ(ERR_IO_PENDING, rv);
2801
2802  rv = callback1.WaitForResult();
2803  EXPECT_EQ(OK, rv);
2804
2805  const HttpResponseInfo* response1 = trans1->GetResponseInfo();
2806  ASSERT_TRUE(response1 != NULL);
2807  ASSERT_TRUE(response1->headers.get() != NULL);
2808  EXPECT_EQ(1, response1->headers->GetContentLength());
2809
2810  LoadTimingInfo load_timing_info1;
2811  EXPECT_TRUE(trans1->GetLoadTimingInfo(&load_timing_info1));
2812  TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_SSL_TIMES);
2813
2814  trans1.reset();
2815
2816  TestCompletionCallback callback2;
2817  scoped_ptr<HttpTransaction> trans2(
2818      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2819
2820  rv = trans2->Start(&request2, callback2.callback(), log.bound());
2821  EXPECT_EQ(ERR_IO_PENDING, rv);
2822
2823  rv = callback2.WaitForResult();
2824  EXPECT_EQ(OK, rv);
2825
2826  const HttpResponseInfo* response2 = trans2->GetResponseInfo();
2827  ASSERT_TRUE(response2 != NULL);
2828  ASSERT_TRUE(response2->headers.get() != NULL);
2829  EXPECT_EQ(2, response2->headers->GetContentLength());
2830
2831  LoadTimingInfo load_timing_info2;
2832  EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
2833  TestLoadTimingReused(load_timing_info2);
2834
2835  EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
2836
2837  trans2.reset();
2838  session->CloseAllConnections();
2839}
2840
2841// Test the load timing for HTTPS requests with an HTTP proxy and a PAC script.
2842TEST_P(HttpNetworkTransactionTest, HttpProxyLoadTimingWithPacTwoRequests) {
2843  HttpRequestInfo request1;
2844  request1.method = "GET";
2845  request1.url = GURL("https://www.google.com/1");
2846
2847  HttpRequestInfo request2;
2848  request2.method = "GET";
2849  request2.url = GURL("https://www.google.com/2");
2850
2851  // Configure against proxy server "myproxy:70".
2852  session_deps_.proxy_service.reset(
2853      ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
2854  CapturingBoundNetLog log;
2855  session_deps_.net_log = log.bound().net_log();
2856  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2857
2858  // Since we have proxy, should try to establish tunnel.
2859  MockWrite data_writes1[] = {
2860    MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2861              "Host: www.google.com\r\n"
2862              "Proxy-Connection: keep-alive\r\n\r\n"),
2863
2864    MockWrite("GET /1 HTTP/1.1\r\n"
2865              "Host: www.google.com\r\n"
2866              "Connection: keep-alive\r\n\r\n"),
2867
2868    MockWrite("GET /2 HTTP/1.1\r\n"
2869              "Host: www.google.com\r\n"
2870              "Connection: keep-alive\r\n\r\n"),
2871  };
2872
2873  // The proxy responds to the connect with a 407, using a persistent
2874  // connection.
2875  MockRead data_reads1[] = {
2876    MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2877
2878    MockRead("HTTP/1.1 200 OK\r\n"),
2879    MockRead("Content-Length: 1\r\n\r\n"),
2880    MockRead(SYNCHRONOUS, "1"),
2881
2882    MockRead("HTTP/1.1 200 OK\r\n"),
2883    MockRead("Content-Length: 2\r\n\r\n"),
2884    MockRead(SYNCHRONOUS, "22"),
2885  };
2886
2887  StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2888                                 data_writes1, arraysize(data_writes1));
2889  session_deps_.socket_factory->AddSocketDataProvider(&data1);
2890  SSLSocketDataProvider ssl(ASYNC, OK);
2891  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2892
2893  TestCompletionCallback callback1;
2894  scoped_ptr<HttpTransaction> trans1(
2895      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2896
2897  int rv = trans1->Start(&request1, callback1.callback(), log.bound());
2898  EXPECT_EQ(ERR_IO_PENDING, rv);
2899
2900  rv = callback1.WaitForResult();
2901  EXPECT_EQ(OK, rv);
2902
2903  const HttpResponseInfo* response1 = trans1->GetResponseInfo();
2904  ASSERT_TRUE(response1 != NULL);
2905  ASSERT_TRUE(response1->headers.get() != NULL);
2906  EXPECT_EQ(1, response1->headers->GetContentLength());
2907
2908  LoadTimingInfo load_timing_info1;
2909  EXPECT_TRUE(trans1->GetLoadTimingInfo(&load_timing_info1));
2910  TestLoadTimingNotReusedWithPac(load_timing_info1,
2911                                 CONNECT_TIMING_HAS_SSL_TIMES);
2912
2913  trans1.reset();
2914
2915  TestCompletionCallback callback2;
2916  scoped_ptr<HttpTransaction> trans2(
2917      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2918
2919  rv = trans2->Start(&request2, callback2.callback(), log.bound());
2920  EXPECT_EQ(ERR_IO_PENDING, rv);
2921
2922  rv = callback2.WaitForResult();
2923  EXPECT_EQ(OK, rv);
2924
2925  const HttpResponseInfo* response2 = trans2->GetResponseInfo();
2926  ASSERT_TRUE(response2 != NULL);
2927  ASSERT_TRUE(response2->headers.get() != NULL);
2928  EXPECT_EQ(2, response2->headers->GetContentLength());
2929
2930  LoadTimingInfo load_timing_info2;
2931  EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
2932  TestLoadTimingReusedWithPac(load_timing_info2);
2933
2934  EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
2935
2936  trans2.reset();
2937  session->CloseAllConnections();
2938}
2939
2940// Test a simple get through an HTTPS Proxy.
2941TEST_P(HttpNetworkTransactionTest, HttpsProxyGet) {
2942  HttpRequestInfo request;
2943  request.method = "GET";
2944  request.url = GURL("http://www.google.com/");
2945
2946  // Configure against https proxy server "proxy:70".
2947  session_deps_.proxy_service.reset(ProxyService::CreateFixed(
2948      "https://proxy:70"));
2949  CapturingBoundNetLog log;
2950  session_deps_.net_log = log.bound().net_log();
2951  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2952
2953  // Since we have proxy, should use full url
2954  MockWrite data_writes1[] = {
2955    MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2956              "Host: www.google.com\r\n"
2957              "Proxy-Connection: keep-alive\r\n\r\n"),
2958  };
2959
2960  MockRead data_reads1[] = {
2961    MockRead("HTTP/1.1 200 OK\r\n"),
2962    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2963    MockRead("Content-Length: 100\r\n\r\n"),
2964    MockRead(SYNCHRONOUS, OK),
2965  };
2966
2967  StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2968                                 data_writes1, arraysize(data_writes1));
2969  session_deps_.socket_factory->AddSocketDataProvider(&data1);
2970  SSLSocketDataProvider ssl(ASYNC, OK);
2971  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2972
2973  TestCompletionCallback callback1;
2974
2975  scoped_ptr<HttpTransaction> trans(
2976      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2977
2978  int rv = trans->Start(&request, callback1.callback(), log.bound());
2979  EXPECT_EQ(ERR_IO_PENDING, rv);
2980
2981  rv = callback1.WaitForResult();
2982  EXPECT_EQ(OK, rv);
2983
2984  LoadTimingInfo load_timing_info;
2985  EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
2986  TestLoadTimingNotReused(load_timing_info,
2987                          CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
2988
2989  const HttpResponseInfo* response = trans->GetResponseInfo();
2990  ASSERT_TRUE(response != NULL);
2991
2992  EXPECT_TRUE(response->headers->IsKeepAlive());
2993  EXPECT_EQ(200, response->headers->response_code());
2994  EXPECT_EQ(100, response->headers->GetContentLength());
2995  EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2996
2997  // The password prompt info should not be set.
2998  EXPECT_TRUE(response->auth_challenge.get() == NULL);
2999}
3000
3001// Test a SPDY get through an HTTPS Proxy.
3002TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGet) {
3003  HttpRequestInfo request;
3004  request.method = "GET";
3005  request.url = GURL("http://www.google.com/");
3006  request.load_flags = 0;
3007
3008  // Configure against https proxy server "proxy:70".
3009  session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3010      "https://proxy:70"));
3011  CapturingBoundNetLog log;
3012  session_deps_.net_log = log.bound().net_log();
3013  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3014
3015  // fetch http://www.google.com/ via SPDY
3016  scoped_ptr<SpdyFrame> req(
3017      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
3018  MockWrite spdy_writes[] = { CreateMockWrite(*req) };
3019
3020  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3021  scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
3022  MockRead spdy_reads[] = {
3023    CreateMockRead(*resp),
3024    CreateMockRead(*data),
3025    MockRead(ASYNC, 0, 0),
3026  };
3027
3028  DelayedSocketData spdy_data(
3029      1,  // wait for one write to finish before reading.
3030      spdy_reads, arraysize(spdy_reads),
3031      spdy_writes, arraysize(spdy_writes));
3032  session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
3033
3034  SSLSocketDataProvider ssl(ASYNC, OK);
3035  ssl.SetNextProto(GetParam());
3036  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3037
3038  TestCompletionCallback callback1;
3039
3040  scoped_ptr<HttpTransaction> trans(
3041      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3042
3043  int rv = trans->Start(&request, callback1.callback(), log.bound());
3044  EXPECT_EQ(ERR_IO_PENDING, rv);
3045
3046  rv = callback1.WaitForResult();
3047  EXPECT_EQ(OK, rv);
3048
3049  LoadTimingInfo load_timing_info;
3050  EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3051  TestLoadTimingNotReused(load_timing_info,
3052                          CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
3053
3054  const HttpResponseInfo* response = trans->GetResponseInfo();
3055  ASSERT_TRUE(response != NULL);
3056  ASSERT_TRUE(response->headers.get() != NULL);
3057  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3058
3059  std::string response_data;
3060  ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
3061  EXPECT_EQ(kUploadData, response_data);
3062}
3063
3064// Verifies that a session which races and wins against the owning transaction
3065// (completing prior to host resolution), doesn't fail the transaction.
3066// Regression test for crbug.com/334413.
3067TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGetWithSessionRace) {
3068  HttpRequestInfo request;
3069  request.method = "GET";
3070  request.url = GURL("http://www.google.com/");
3071  request.load_flags = 0;
3072
3073  // Configure SPDY proxy server "proxy:70".
3074  session_deps_.proxy_service.reset(
3075      ProxyService::CreateFixed("https://proxy:70"));
3076  CapturingBoundNetLog log;
3077  session_deps_.net_log = log.bound().net_log();
3078  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3079
3080  // Fetch http://www.google.com/ through the SPDY proxy.
3081  scoped_ptr<SpdyFrame> req(
3082      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
3083  MockWrite spdy_writes[] = {CreateMockWrite(*req)};
3084
3085  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3086  scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
3087  MockRead spdy_reads[] = {
3088      CreateMockRead(*resp), CreateMockRead(*data), MockRead(ASYNC, 0, 0),
3089  };
3090
3091  DelayedSocketData spdy_data(
3092      1,  // wait for one write to finish before reading.
3093      spdy_reads,
3094      arraysize(spdy_reads),
3095      spdy_writes,
3096      arraysize(spdy_writes));
3097  session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
3098
3099  SSLSocketDataProvider ssl(ASYNC, OK);
3100  ssl.SetNextProto(GetParam());
3101  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3102
3103  TestCompletionCallback callback1;
3104
3105  scoped_ptr<HttpTransaction> trans(
3106      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3107
3108  // Stall the hostname resolution begun by the transaction.
3109  session_deps_.host_resolver->set_synchronous_mode(false);
3110  session_deps_.host_resolver->set_ondemand_mode(true);
3111
3112  int rv = trans->Start(&request, callback1.callback(), log.bound());
3113  EXPECT_EQ(ERR_IO_PENDING, rv);
3114
3115  // Race a session to the proxy, which completes first.
3116  session_deps_.host_resolver->set_ondemand_mode(false);
3117  SpdySessionKey key(
3118      HostPortPair("proxy", 70), ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
3119  base::WeakPtr<SpdySession> spdy_session =
3120      CreateSecureSpdySession(session, key, log.bound());
3121
3122  // Unstall the resolution begun by the transaction.
3123  session_deps_.host_resolver->set_ondemand_mode(true);
3124  session_deps_.host_resolver->ResolveAllPending();
3125
3126  EXPECT_FALSE(callback1.have_result());
3127  rv = callback1.WaitForResult();
3128  EXPECT_EQ(OK, rv);
3129
3130  const HttpResponseInfo* response = trans->GetResponseInfo();
3131  ASSERT_TRUE(response != NULL);
3132  ASSERT_TRUE(response->headers.get() != NULL);
3133  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3134
3135  std::string response_data;
3136  ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
3137  EXPECT_EQ(kUploadData, response_data);
3138}
3139
3140// Test a SPDY get through an HTTPS Proxy.
3141TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGetWithProxyAuth) {
3142  HttpRequestInfo request;
3143  request.method = "GET";
3144  request.url = GURL("http://www.google.com/");
3145  request.load_flags = 0;
3146
3147  // Configure against https proxy server "myproxy:70".
3148  session_deps_.proxy_service.reset(
3149      ProxyService::CreateFixed("https://myproxy:70"));
3150  CapturingBoundNetLog log;
3151  session_deps_.net_log = log.bound().net_log();
3152  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3153
3154  // The first request will be a bare GET, the second request will be a
3155  // GET with a Proxy-Authorization header.
3156  scoped_ptr<SpdyFrame> req_get(
3157      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
3158  const char* const kExtraAuthorizationHeaders[] = {
3159    "proxy-authorization", "Basic Zm9vOmJhcg=="
3160  };
3161  scoped_ptr<SpdyFrame> req_get_authorization(
3162      spdy_util_.ConstructSpdyGet(kExtraAuthorizationHeaders,
3163                                  arraysize(kExtraAuthorizationHeaders) / 2,
3164                                  false,
3165                                  3,
3166                                  LOWEST,
3167                                  false));
3168  MockWrite spdy_writes[] = {
3169    CreateMockWrite(*req_get, 1),
3170    CreateMockWrite(*req_get_authorization, 4),
3171  };
3172
3173  // The first response is a 407 proxy authentication challenge, and the second
3174  // response will be a 200 response since the second request includes a valid
3175  // Authorization header.
3176  const char* const kExtraAuthenticationHeaders[] = {
3177    "proxy-authenticate", "Basic realm=\"MyRealm1\""
3178  };
3179  scoped_ptr<SpdyFrame> resp_authentication(
3180      spdy_util_.ConstructSpdySynReplyError(
3181          "407 Proxy Authentication Required",
3182          kExtraAuthenticationHeaders, arraysize(kExtraAuthenticationHeaders)/2,
3183          1));
3184  scoped_ptr<SpdyFrame> body_authentication(
3185      spdy_util_.ConstructSpdyBodyFrame(1, true));
3186  scoped_ptr<SpdyFrame> resp_data(
3187      spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
3188  scoped_ptr<SpdyFrame> body_data(spdy_util_.ConstructSpdyBodyFrame(3, true));
3189  MockRead spdy_reads[] = {
3190    CreateMockRead(*resp_authentication, 2),
3191    CreateMockRead(*body_authentication, 3),
3192    CreateMockRead(*resp_data, 5),
3193    CreateMockRead(*body_data, 6),
3194    MockRead(ASYNC, 0, 7),
3195  };
3196
3197  OrderedSocketData data(
3198      spdy_reads, arraysize(spdy_reads),
3199      spdy_writes, arraysize(spdy_writes));
3200  session_deps_.socket_factory->AddSocketDataProvider(&data);
3201
3202  SSLSocketDataProvider ssl(ASYNC, OK);
3203  ssl.SetNextProto(GetParam());
3204  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3205
3206  TestCompletionCallback callback1;
3207
3208  scoped_ptr<HttpTransaction> trans(
3209      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3210
3211  int rv = trans->Start(&request, callback1.callback(), log.bound());
3212  EXPECT_EQ(ERR_IO_PENDING, rv);
3213
3214  rv = callback1.WaitForResult();
3215  EXPECT_EQ(OK, rv);
3216
3217  const HttpResponseInfo* const response = trans->GetResponseInfo();
3218
3219  ASSERT_TRUE(response != NULL);
3220  ASSERT_TRUE(response->headers.get() != NULL);
3221  EXPECT_EQ(407, response->headers->response_code());
3222  EXPECT_TRUE(response->was_fetched_via_spdy);
3223  EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
3224
3225  TestCompletionCallback callback2;
3226
3227  rv = trans->RestartWithAuth(
3228      AuthCredentials(kFoo, kBar), callback2.callback());
3229  EXPECT_EQ(ERR_IO_PENDING, rv);
3230
3231  rv = callback2.WaitForResult();
3232  EXPECT_EQ(OK, rv);
3233
3234  const HttpResponseInfo* const response_restart = trans->GetResponseInfo();
3235
3236  ASSERT_TRUE(response_restart != NULL);
3237  ASSERT_TRUE(response_restart->headers.get() != NULL);
3238  EXPECT_EQ(200, response_restart->headers->response_code());
3239  // The password prompt info should not be set.
3240  EXPECT_TRUE(response_restart->auth_challenge.get() == NULL);
3241}
3242
3243// Test a SPDY CONNECT through an HTTPS Proxy to an HTTPS (non-SPDY) Server.
3244TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectHttps) {
3245  HttpRequestInfo request;
3246  request.method = "GET";
3247  request.url = GURL("https://www.google.com/");
3248  request.load_flags = 0;
3249
3250  // Configure against https proxy server "proxy:70".
3251  session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3252      "https://proxy:70"));
3253  CapturingBoundNetLog log;
3254  session_deps_.net_log = log.bound().net_log();
3255  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3256
3257  scoped_ptr<HttpTransaction> trans(
3258      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3259
3260  // CONNECT to www.google.com:443 via SPDY
3261  scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(NULL, 0, 1,
3262                                                                LOWEST));
3263  // fetch https://www.google.com/ via HTTP
3264
3265  const char get[] = "GET / HTTP/1.1\r\n"
3266    "Host: www.google.com\r\n"
3267    "Connection: keep-alive\r\n\r\n";
3268  scoped_ptr<SpdyFrame> wrapped_get(
3269      spdy_util_.ConstructSpdyBodyFrame(1, get, strlen(get), false));
3270  scoped_ptr<SpdyFrame> conn_resp(
3271      spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3272  const char resp[] = "HTTP/1.1 200 OK\r\n"
3273      "Content-Length: 10\r\n\r\n";
3274  scoped_ptr<SpdyFrame> wrapped_get_resp(
3275      spdy_util_.ConstructSpdyBodyFrame(1, resp, strlen(resp), false));
3276  scoped_ptr<SpdyFrame> wrapped_body(
3277      spdy_util_.ConstructSpdyBodyFrame(1, "1234567890", 10, false));
3278  scoped_ptr<SpdyFrame> window_update(
3279      spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp->size()));
3280
3281  MockWrite spdy_writes[] = {
3282      CreateMockWrite(*connect, 1),
3283      CreateMockWrite(*wrapped_get, 3),
3284      CreateMockWrite(*window_update, 5),
3285  };
3286
3287  MockRead spdy_reads[] = {
3288    CreateMockRead(*conn_resp, 2, ASYNC),
3289    CreateMockRead(*wrapped_get_resp, 4, ASYNC),
3290    CreateMockRead(*wrapped_body, 6, ASYNC),
3291    CreateMockRead(*wrapped_body, 7, ASYNC),
3292    MockRead(ASYNC, 0, 8),
3293  };
3294
3295  OrderedSocketData spdy_data(
3296      spdy_reads, arraysize(spdy_reads),
3297      spdy_writes, arraysize(spdy_writes));
3298  session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
3299
3300  SSLSocketDataProvider ssl(ASYNC, OK);
3301  ssl.SetNextProto(GetParam());
3302  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3303  SSLSocketDataProvider ssl2(ASYNC, OK);
3304  ssl2.was_npn_negotiated = false;
3305  ssl2.protocol_negotiated = kProtoUnknown;
3306  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
3307
3308  TestCompletionCallback callback1;
3309
3310  int rv = trans->Start(&request, callback1.callback(), log.bound());
3311  EXPECT_EQ(ERR_IO_PENDING, rv);
3312
3313  rv = callback1.WaitForResult();
3314  EXPECT_EQ(OK, rv);
3315
3316  LoadTimingInfo load_timing_info;
3317  EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3318  TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
3319
3320  const HttpResponseInfo* response = trans->GetResponseInfo();
3321  ASSERT_TRUE(response != NULL);
3322  ASSERT_TRUE(response->headers.get() != NULL);
3323  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3324
3325  std::string response_data;
3326  ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
3327  EXPECT_EQ("1234567890", response_data);
3328}
3329
3330// Test a SPDY CONNECT through an HTTPS Proxy to a SPDY server.
3331TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectSpdy) {
3332  HttpRequestInfo request;
3333  request.method = "GET";
3334  request.url = GURL("https://www.google.com/");
3335  request.load_flags = 0;
3336
3337  // Configure against https proxy server "proxy:70".
3338  session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3339      "https://proxy:70"));
3340  CapturingBoundNetLog log;
3341  session_deps_.net_log = log.bound().net_log();
3342  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3343
3344  scoped_ptr<HttpTransaction> trans(
3345      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3346
3347  // CONNECT to www.google.com:443 via SPDY
3348  scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(NULL, 0, 1,
3349                                                                LOWEST));
3350  // fetch https://www.google.com/ via SPDY
3351  const char* const kMyUrl = "https://www.google.com/";
3352  scoped_ptr<SpdyFrame> get(
3353      spdy_util_.ConstructSpdyGet(kMyUrl, false, 1, LOWEST));
3354  scoped_ptr<SpdyFrame> wrapped_get(
3355      spdy_util_.ConstructWrappedSpdyFrame(get, 1));
3356  scoped_ptr<SpdyFrame> conn_resp(
3357      spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3358  scoped_ptr<SpdyFrame> get_resp(
3359      spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3360  scoped_ptr<SpdyFrame> wrapped_get_resp(
3361      spdy_util_.ConstructWrappedSpdyFrame(get_resp, 1));
3362  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
3363  scoped_ptr<SpdyFrame> wrapped_body(
3364      spdy_util_.ConstructWrappedSpdyFrame(body, 1));
3365  scoped_ptr<SpdyFrame> window_update_get_resp(
3366      spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp->size()));
3367  scoped_ptr<SpdyFrame> window_update_body(
3368      spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_body->size()));
3369
3370  MockWrite spdy_writes[] = {
3371      CreateMockWrite(*connect, 1),
3372      CreateMockWrite(*wrapped_get, 3),
3373      CreateMockWrite(*window_update_get_resp, 5),
3374      CreateMockWrite(*window_update_body, 7),
3375  };
3376
3377  MockRead spdy_reads[] = {
3378    CreateMockRead(*conn_resp, 2, ASYNC),
3379    CreateMockRead(*wrapped_get_resp, 4, ASYNC),
3380    CreateMockRead(*wrapped_body, 6, ASYNC),
3381    MockRead(ASYNC, 0, 8),
3382  };
3383
3384  OrderedSocketData spdy_data(
3385      spdy_reads, arraysize(spdy_reads),
3386      spdy_writes, arraysize(spdy_writes));
3387  session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
3388
3389  SSLSocketDataProvider ssl(ASYNC, OK);
3390  ssl.SetNextProto(GetParam());
3391  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3392  SSLSocketDataProvider ssl2(ASYNC, OK);
3393  ssl2.SetNextProto(GetParam());
3394  ssl2.protocol_negotiated = GetParam();
3395  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
3396
3397  TestCompletionCallback callback1;
3398
3399  int rv = trans->Start(&request, callback1.callback(), log.bound());
3400  EXPECT_EQ(ERR_IO_PENDING, rv);
3401
3402  rv = callback1.WaitForResult();
3403  EXPECT_EQ(OK, rv);
3404
3405  LoadTimingInfo load_timing_info;
3406  EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3407  TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
3408
3409  const HttpResponseInfo* response = trans->GetResponseInfo();
3410  ASSERT_TRUE(response != NULL);
3411  ASSERT_TRUE(response->headers.get() != NULL);
3412  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3413
3414  std::string response_data;
3415  ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
3416  EXPECT_EQ(kUploadData, response_data);
3417}
3418
3419// Test a SPDY CONNECT failure through an HTTPS Proxy.
3420TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectFailure) {
3421  HttpRequestInfo request;
3422  request.method = "GET";
3423  request.url = GURL("https://www.google.com/");
3424  request.load_flags = 0;
3425
3426  // Configure against https proxy server "proxy:70".
3427  session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3428      "https://proxy:70"));
3429  CapturingBoundNetLog log;
3430  session_deps_.net_log = log.bound().net_log();
3431  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3432
3433  scoped_ptr<HttpTransaction> trans(
3434      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3435
3436  // CONNECT to www.google.com:443 via SPDY
3437  scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(NULL, 0, 1,
3438                                                                LOWEST));
3439  scoped_ptr<SpdyFrame> get(
3440      spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
3441
3442  MockWrite spdy_writes[] = {
3443      CreateMockWrite(*connect, 1),
3444      CreateMockWrite(*get, 3),
3445  };
3446
3447  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdySynReplyError(1));
3448  scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
3449  MockRead spdy_reads[] = {
3450    CreateMockRead(*resp, 2, ASYNC),
3451    MockRead(ASYNC, 0, 4),
3452  };
3453
3454  OrderedSocketData spdy_data(
3455      spdy_reads, arraysize(spdy_reads),
3456      spdy_writes, arraysize(spdy_writes));
3457  session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
3458
3459  SSLSocketDataProvider ssl(ASYNC, OK);
3460  ssl.SetNextProto(GetParam());
3461  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3462  SSLSocketDataProvider ssl2(ASYNC, OK);
3463  ssl2.SetNextProto(GetParam());
3464  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
3465
3466  TestCompletionCallback callback1;
3467
3468  int rv = trans->Start(&request, callback1.callback(), log.bound());
3469  EXPECT_EQ(ERR_IO_PENDING, rv);
3470
3471  rv = callback1.WaitForResult();
3472  EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
3473
3474  // TODO(ttuttle): Anything else to check here?
3475}
3476
3477// Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
3478// HTTPS Proxy to different servers.
3479TEST_P(HttpNetworkTransactionTest,
3480       HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsTwoServers) {
3481  // Configure against https proxy server "proxy:70".
3482  session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3483      "https://proxy:70"));
3484  CapturingBoundNetLog log;
3485  session_deps_.net_log = log.bound().net_log();
3486  scoped_refptr<HttpNetworkSession> session(
3487      SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
3488
3489  HttpRequestInfo request1;
3490  request1.method = "GET";
3491  request1.url = GURL("https://www.google.com/");
3492  request1.load_flags = 0;
3493
3494  HttpRequestInfo request2;
3495  request2.method = "GET";
3496  request2.url = GURL("https://news.google.com/");
3497  request2.load_flags = 0;
3498
3499  // CONNECT to www.google.com:443 via SPDY.
3500  scoped_ptr<SpdyFrame> connect1(spdy_util_.ConstructSpdyConnect(NULL, 0, 1,
3501                                                                 LOWEST));
3502  scoped_ptr<SpdyFrame> conn_resp1(
3503      spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3504
3505  // Fetch https://www.google.com/ via HTTP.
3506  const char get1[] = "GET / HTTP/1.1\r\n"
3507      "Host: www.google.com\r\n"
3508      "Connection: keep-alive\r\n\r\n";
3509  scoped_ptr<SpdyFrame> wrapped_get1(
3510      spdy_util_.ConstructSpdyBodyFrame(1, get1, strlen(get1), false));
3511  const char resp1[] = "HTTP/1.1 200 OK\r\n"
3512      "Content-Length: 1\r\n\r\n";
3513  scoped_ptr<SpdyFrame> wrapped_get_resp1(
3514      spdy_util_.ConstructSpdyBodyFrame(1, resp1, strlen(resp1), false));
3515  scoped_ptr<SpdyFrame> wrapped_body1(
3516      spdy_util_.ConstructSpdyBodyFrame(1, "1", 1, false));
3517  scoped_ptr<SpdyFrame> window_update(
3518      spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp1->size()));
3519
3520  // CONNECT to news.google.com:443 via SPDY.
3521  SpdyHeaderBlock connect2_block;
3522  connect2_block[spdy_util_.GetMethodKey()] = "CONNECT";
3523  connect2_block[spdy_util_.GetPathKey()] = "news.google.com:443";
3524  connect2_block[spdy_util_.GetHostKey()] = "news.google.com";
3525  spdy_util_.MaybeAddVersionHeader(&connect2_block);
3526  scoped_ptr<SpdyFrame> connect2(
3527      spdy_util_.ConstructSpdySyn(3, connect2_block, LOWEST, false, false));
3528
3529  scoped_ptr<SpdyFrame> conn_resp2(
3530      spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
3531
3532  // Fetch https://news.google.com/ via HTTP.
3533  const char get2[] = "GET / HTTP/1.1\r\n"
3534      "Host: news.google.com\r\n"
3535      "Connection: keep-alive\r\n\r\n";
3536  scoped_ptr<SpdyFrame> wrapped_get2(
3537      spdy_util_.ConstructSpdyBodyFrame(3, get2, strlen(get2), false));
3538  const char resp2[] = "HTTP/1.1 200 OK\r\n"
3539      "Content-Length: 2\r\n\r\n";
3540  scoped_ptr<SpdyFrame> wrapped_get_resp2(
3541      spdy_util_.ConstructSpdyBodyFrame(3, resp2, strlen(resp2), false));
3542  scoped_ptr<SpdyFrame> wrapped_body2(
3543      spdy_util_.ConstructSpdyBodyFrame(3, "22", 2, false));
3544
3545  MockWrite spdy_writes[] = {
3546      CreateMockWrite(*connect1, 0),
3547      CreateMockWrite(*wrapped_get1, 2),
3548      CreateMockWrite(*connect2, 5),
3549      CreateMockWrite(*wrapped_get2, 7),
3550  };
3551
3552  MockRead spdy_reads[] = {
3553    CreateMockRead(*conn_resp1, 1, ASYNC),
3554    CreateMockRead(*wrapped_get_resp1, 3, ASYNC),
3555    CreateMockRead(*wrapped_body1, 4, ASYNC),
3556    CreateMockRead(*conn_resp2, 6, ASYNC),
3557    CreateMockRead(*wrapped_get_resp2, 8, ASYNC),
3558    CreateMockRead(*wrapped_body2, 9, ASYNC),
3559    MockRead(ASYNC, 0, 10),
3560  };
3561
3562  DeterministicSocketData spdy_data(
3563      spdy_reads, arraysize(spdy_reads),
3564      spdy_writes, arraysize(spdy_writes));
3565  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&spdy_data);
3566
3567  SSLSocketDataProvider ssl(ASYNC, OK);
3568  ssl.SetNextProto(GetParam());
3569  session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
3570  SSLSocketDataProvider ssl2(ASYNC, OK);
3571  ssl2.was_npn_negotiated = false;
3572  ssl2.protocol_negotiated = kProtoUnknown;
3573  session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2);
3574  SSLSocketDataProvider ssl3(ASYNC, OK);
3575  ssl3.was_npn_negotiated = false;
3576  ssl3.protocol_negotiated = kProtoUnknown;
3577  session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl3);
3578
3579  TestCompletionCallback callback;
3580
3581  scoped_ptr<HttpTransaction> trans(
3582      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3583  int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
3584  EXPECT_EQ(ERR_IO_PENDING, rv);
3585  // The first connect and request, each of their responses, and the body.
3586  spdy_data.RunFor(5);
3587
3588  rv = callback.WaitForResult();
3589  EXPECT_EQ(OK, rv);
3590
3591  LoadTimingInfo load_timing_info;
3592  EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3593  TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
3594
3595  const HttpResponseInfo* response = trans->GetResponseInfo();
3596  ASSERT_TRUE(response != NULL);
3597  ASSERT_TRUE(response->headers.get() != NULL);
3598  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3599
3600  std::string response_data;
3601  scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(256));
3602  EXPECT_EQ(1, trans->Read(buf.get(), 256, callback.callback()));
3603
3604  scoped_ptr<HttpTransaction> trans2(
3605      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3606  rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
3607  EXPECT_EQ(ERR_IO_PENDING, rv);
3608
3609  // The second connect and request, each of their responses, and the body.
3610  spdy_data.RunFor(5);
3611  rv = callback.WaitForResult();
3612  EXPECT_EQ(OK, rv);
3613
3614  LoadTimingInfo load_timing_info2;
3615  EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
3616  // Even though the SPDY connection is reused, a new tunnelled connection has
3617  // to be created, so the socket's load timing looks like a fresh connection.
3618  TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_SSL_TIMES);
3619
3620  // The requests should have different IDs, since they each are using their own
3621  // separate stream.
3622  EXPECT_NE(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
3623
3624  EXPECT_EQ(2, trans2->Read(buf.get(), 256, callback.callback()));
3625}
3626
3627// Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
3628// HTTPS Proxy to the same server.
3629TEST_P(HttpNetworkTransactionTest,
3630       HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsSameServer) {
3631  // Configure against https proxy server "proxy:70".
3632  session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3633      "https://proxy:70"));
3634  CapturingBoundNetLog log;
3635  session_deps_.net_log = log.bound().net_log();
3636  scoped_refptr<HttpNetworkSession> session(
3637      SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
3638
3639  HttpRequestInfo request1;
3640  request1.method = "GET";
3641  request1.url = GURL("https://www.google.com/");
3642  request1.load_flags = 0;
3643
3644  HttpRequestInfo request2;
3645  request2.method = "GET";
3646  request2.url = GURL("https://www.google.com/2");
3647  request2.load_flags = 0;
3648
3649  // CONNECT to www.google.com:443 via SPDY.
3650  scoped_ptr<SpdyFrame> connect1(spdy_util_.ConstructSpdyConnect(NULL, 0, 1,
3651                                                                 LOWEST));
3652  scoped_ptr<SpdyFrame> conn_resp1(
3653      spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3654
3655  // Fetch https://www.google.com/ via HTTP.
3656  const char get1[] = "GET / HTTP/1.1\r\n"
3657      "Host: www.google.com\r\n"
3658      "Connection: keep-alive\r\n\r\n";
3659  scoped_ptr<SpdyFrame> wrapped_get1(
3660      spdy_util_.ConstructSpdyBodyFrame(1, get1, strlen(get1), false));
3661  const char resp1[] = "HTTP/1.1 200 OK\r\n"
3662      "Content-Length: 1\r\n\r\n";
3663  scoped_ptr<SpdyFrame> wrapped_get_resp1(
3664      spdy_util_.ConstructSpdyBodyFrame(1, resp1, strlen(resp1), false));
3665  scoped_ptr<SpdyFrame> wrapped_body1(
3666      spdy_util_.ConstructSpdyBodyFrame(1, "1", 1, false));
3667  scoped_ptr<SpdyFrame> window_update(
3668      spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp1->size()));
3669
3670  // Fetch https://www.google.com/2 via HTTP.
3671  const char get2[] = "GET /2 HTTP/1.1\r\n"
3672      "Host: www.google.com\r\n"
3673      "Connection: keep-alive\r\n\r\n";
3674  scoped_ptr<SpdyFrame> wrapped_get2(
3675      spdy_util_.ConstructSpdyBodyFrame(1, get2, strlen(get2), false));
3676  const char resp2[] = "HTTP/1.1 200 OK\r\n"
3677      "Content-Length: 2\r\n\r\n";
3678  scoped_ptr<SpdyFrame> wrapped_get_resp2(
3679      spdy_util_.ConstructSpdyBodyFrame(1, resp2, strlen(resp2), false));
3680  scoped_ptr<SpdyFrame> wrapped_body2(
3681      spdy_util_.ConstructSpdyBodyFrame(1, "22", 2, false));
3682
3683  MockWrite spdy_writes[] = {
3684      CreateMockWrite(*connect1, 0),
3685      CreateMockWrite(*wrapped_get1, 2),
3686      CreateMockWrite(*wrapped_get2, 5),
3687  };
3688
3689  MockRead spdy_reads[] = {
3690    CreateMockRead(*conn_resp1, 1, ASYNC),
3691    CreateMockRead(*wrapped_get_resp1, 3, ASYNC),
3692    CreateMockRead(*wrapped_body1, 4, ASYNC),
3693    CreateMockRead(*wrapped_get_resp2, 6, ASYNC),
3694    CreateMockRead(*wrapped_body2, 7, ASYNC),
3695    MockRead(ASYNC, 0, 8),
3696  };
3697
3698  DeterministicSocketData spdy_data(
3699      spdy_reads, arraysize(spdy_reads),
3700      spdy_writes, arraysize(spdy_writes));
3701  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&spdy_data);
3702
3703  SSLSocketDataProvider ssl(ASYNC, OK);
3704  ssl.SetNextProto(GetParam());
3705  session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
3706  SSLSocketDataProvider ssl2(ASYNC, OK);
3707  ssl2.was_npn_negotiated = false;
3708  ssl2.protocol_negotiated = kProtoUnknown;
3709  session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2);
3710
3711  TestCompletionCallback callback;
3712
3713  scoped_ptr<HttpTransaction> trans(
3714      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3715  int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
3716  EXPECT_EQ(ERR_IO_PENDING, rv);
3717  // The first connect and request, each of their responses, and the body.
3718  spdy_data.RunFor(5);
3719
3720  rv = callback.WaitForResult();
3721  EXPECT_EQ(OK, rv);
3722
3723  LoadTimingInfo load_timing_info;
3724  EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3725  TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
3726
3727  const HttpResponseInfo* response = trans->GetResponseInfo();
3728  ASSERT_TRUE(response != NULL);
3729  ASSERT_TRUE(response->headers.get() != NULL);
3730  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3731
3732  std::string response_data;
3733  scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(256));
3734  EXPECT_EQ(1, trans->Read(buf.get(), 256, callback.callback()));
3735  trans.reset();
3736
3737  scoped_ptr<HttpTransaction> trans2(
3738      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3739  rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
3740  EXPECT_EQ(ERR_IO_PENDING, rv);
3741
3742  // The second request, response, and body.  There should not be a second
3743  // connect.
3744  spdy_data.RunFor(3);
3745  rv = callback.WaitForResult();
3746  EXPECT_EQ(OK, rv);
3747
3748  LoadTimingInfo load_timing_info2;
3749  EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
3750  TestLoadTimingReused(load_timing_info2);
3751
3752  // The requests should have the same ID.
3753  EXPECT_EQ(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
3754
3755  EXPECT_EQ(2, trans2->Read(buf.get(), 256, callback.callback()));
3756}
3757
3758// Test load timing in the case of of two HTTP requests through a SPDY HTTPS
3759// Proxy to different servers.
3760TEST_P(HttpNetworkTransactionTest,
3761       HttpsProxySpdyLoadTimingTwoHttpRequests) {
3762  // Configure against https proxy server "proxy:70".
3763  session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3764      "https://proxy:70"));
3765  CapturingBoundNetLog log;
3766  session_deps_.net_log = log.bound().net_log();
3767  scoped_refptr<HttpNetworkSession> session(
3768      SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
3769
3770  HttpRequestInfo request1;
3771  request1.method = "GET";
3772  request1.url = GURL("http://www.google.com/");
3773  request1.load_flags = 0;
3774
3775  HttpRequestInfo request2;
3776  request2.method = "GET";
3777  request2.url = GURL("http://news.google.com/");
3778  request2.load_flags = 0;
3779
3780  // http://www.google.com/
3781  scoped_ptr<SpdyHeaderBlock> headers(
3782      spdy_util_.ConstructGetHeaderBlockForProxy("http://www.google.com/"));
3783  scoped_ptr<SpdyFrame> get1(
3784      spdy_util_.ConstructSpdySyn(1, *headers, LOWEST, false, true));
3785  scoped_ptr<SpdyFrame> get_resp1(
3786      spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3787  scoped_ptr<SpdyFrame> body1(
3788      spdy_util_.ConstructSpdyBodyFrame(1, "1", 1, true));
3789
3790  // http://news.google.com/
3791  scoped_ptr<SpdyHeaderBlock> headers2(
3792      spdy_util_.ConstructGetHeaderBlockForProxy("http://news.google.com/"));
3793  scoped_ptr<SpdyFrame> get2(
3794      spdy_util_.ConstructSpdySyn(3, *headers2, LOWEST, false, true));
3795  scoped_ptr<SpdyFrame> get_resp2(
3796      spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
3797  scoped_ptr<SpdyFrame> body2(
3798      spdy_util_.ConstructSpdyBodyFrame(3, "22", 2, true));
3799
3800  MockWrite spdy_writes[] = {
3801      CreateMockWrite(*get1, 0),
3802      CreateMockWrite(*get2, 3),
3803  };
3804
3805  MockRead spdy_reads[] = {
3806    CreateMockRead(*get_resp1, 1, ASYNC),
3807    CreateMockRead(*body1, 2, ASYNC),
3808    CreateMockRead(*get_resp2, 4, ASYNC),
3809    CreateMockRead(*body2, 5, ASYNC),
3810    MockRead(ASYNC, 0, 6),
3811  };
3812
3813  DeterministicSocketData spdy_data(
3814      spdy_reads, arraysize(spdy_reads),
3815      spdy_writes, arraysize(spdy_writes));
3816  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&spdy_data);
3817
3818  SSLSocketDataProvider ssl(ASYNC, OK);
3819  ssl.SetNextProto(GetParam());
3820  session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
3821
3822  TestCompletionCallback callback;
3823
3824  scoped_ptr<HttpTransaction> trans(
3825      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3826  int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
3827  EXPECT_EQ(ERR_IO_PENDING, rv);
3828  spdy_data.RunFor(2);
3829
3830  rv = callback.WaitForResult();
3831  EXPECT_EQ(OK, rv);
3832
3833  LoadTimingInfo load_timing_info;
3834  EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3835  TestLoadTimingNotReused(load_timing_info,
3836                          CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
3837
3838  const HttpResponseInfo* response = trans->GetResponseInfo();
3839  ASSERT_TRUE(response != NULL);
3840  ASSERT_TRUE(response->headers.get() != NULL);
3841  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3842
3843  std::string response_data;
3844  scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(256));
3845  EXPECT_EQ(ERR_IO_PENDING, trans->Read(buf.get(), 256, callback.callback()));
3846  spdy_data.RunFor(1);
3847  EXPECT_EQ(1, callback.WaitForResult());
3848  // Delete the first request, so the second one can reuse the socket.
3849  trans.reset();
3850
3851  scoped_ptr<HttpTransaction> trans2(
3852      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3853  rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
3854  EXPECT_EQ(ERR_IO_PENDING, rv);
3855
3856  spdy_data.RunFor(2);
3857  rv = callback.WaitForResult();
3858  EXPECT_EQ(OK, rv);
3859
3860  LoadTimingInfo load_timing_info2;
3861  EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
3862  TestLoadTimingReused(load_timing_info2);
3863
3864  // The requests should have the same ID.
3865  EXPECT_EQ(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
3866
3867  EXPECT_EQ(ERR_IO_PENDING, trans2->Read(buf.get(), 256, callback.callback()));
3868  spdy_data.RunFor(1);
3869  EXPECT_EQ(2, callback.WaitForResult());
3870}
3871
3872// Test the challenge-response-retry sequence through an HTTPS Proxy
3873TEST_P(HttpNetworkTransactionTest, HttpsProxyAuthRetry) {
3874  HttpRequestInfo request;
3875  request.method = "GET";
3876  request.url = GURL("http://www.google.com/");
3877  // when the no authentication data flag is set.
3878  request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
3879
3880  // Configure against https proxy server "myproxy:70".
3881  session_deps_.proxy_service.reset(
3882      ProxyService::CreateFixed("https://myproxy:70"));
3883  CapturingBoundNetLog log;
3884  session_deps_.net_log = log.bound().net_log();
3885  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3886
3887  // Since we have proxy, should use full url
3888  MockWrite data_writes1[] = {
3889    MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
3890              "Host: www.google.com\r\n"
3891              "Proxy-Connection: keep-alive\r\n\r\n"),
3892
3893    // After calling trans->RestartWithAuth(), this is the request we should
3894    // be issuing -- the final header line contains the credentials.
3895    MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
3896              "Host: www.google.com\r\n"
3897              "Proxy-Connection: keep-alive\r\n"
3898              "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3899  };
3900
3901  // The proxy responds to the GET with a 407, using a persistent
3902  // connection.
3903  MockRead data_reads1[] = {
3904    // No credentials.
3905    MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3906    MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3907    MockRead("Proxy-Connection: keep-alive\r\n"),
3908    MockRead("Content-Length: 0\r\n\r\n"),
3909
3910    MockRead("HTTP/1.1 200 OK\r\n"),
3911    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3912    MockRead("Content-Length: 100\r\n\r\n"),
3913    MockRead(SYNCHRONOUS, OK),
3914  };
3915
3916  StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3917                                 data_writes1, arraysize(data_writes1));
3918  session_deps_.socket_factory->AddSocketDataProvider(&data1);
3919  SSLSocketDataProvider ssl(ASYNC, OK);
3920  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3921
3922  TestCompletionCallback callback1;
3923
3924  scoped_ptr<HttpTransaction> trans(
3925      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3926
3927  int rv = trans->Start(&request, callback1.callback(), log.bound());
3928  EXPECT_EQ(ERR_IO_PENDING, rv);
3929
3930  rv = callback1.WaitForResult();
3931  EXPECT_EQ(OK, rv);
3932
3933  LoadTimingInfo load_timing_info;
3934  EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3935  TestLoadTimingNotReused(load_timing_info,
3936                          CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
3937
3938  const HttpResponseInfo* response = trans->GetResponseInfo();
3939  ASSERT_TRUE(response != NULL);
3940  ASSERT_FALSE(response->headers.get() == NULL);
3941  EXPECT_EQ(407, response->headers->response_code());
3942  EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3943  EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
3944
3945  TestCompletionCallback callback2;
3946
3947  rv = trans->RestartWithAuth(
3948      AuthCredentials(kFoo, kBar), callback2.callback());
3949  EXPECT_EQ(ERR_IO_PENDING, rv);
3950
3951  rv = callback2.WaitForResult();
3952  EXPECT_EQ(OK, rv);
3953
3954  load_timing_info = LoadTimingInfo();
3955  EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3956  // Retrying with HTTP AUTH is considered to be reusing a socket.
3957  TestLoadTimingReused(load_timing_info);
3958
3959  response = trans->GetResponseInfo();
3960  ASSERT_TRUE(response != NULL);
3961
3962  EXPECT_TRUE(response->headers->IsKeepAlive());
3963  EXPECT_EQ(200, response->headers->response_code());
3964  EXPECT_EQ(100, response->headers->GetContentLength());
3965  EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3966
3967  // The password prompt info should not be set.
3968  EXPECT_TRUE(response->auth_challenge.get() == NULL);
3969}
3970
3971void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
3972    const MockRead& status, int expected_status) {
3973  HttpRequestInfo request;
3974  request.method = "GET";
3975  request.url = GURL("https://www.google.com/");
3976  request.load_flags = 0;
3977
3978  // Configure against proxy server "myproxy:70".
3979  session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
3980  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3981
3982  // Since we have proxy, should try to establish tunnel.
3983  MockWrite data_writes[] = {
3984    MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
3985              "Host: www.google.com\r\n"
3986              "Proxy-Connection: keep-alive\r\n\r\n"),
3987  };
3988
3989  MockRead data_reads[] = {
3990    status,
3991    MockRead("Content-Length: 10\r\n\r\n"),
3992    // No response body because the test stops reading here.
3993    MockRead(SYNCHRONOUS, ERR_UNEXPECTED),  // Should not be reached.
3994  };
3995
3996  StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3997                                data_writes, arraysize(data_writes));
3998  session_deps_.socket_factory->AddSocketDataProvider(&data);
3999
4000  TestCompletionCallback callback;
4001
4002  scoped_ptr<HttpTransaction> trans(
4003      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4004
4005  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
4006  EXPECT_EQ(ERR_IO_PENDING, rv);
4007
4008  rv = callback.WaitForResult();
4009  EXPECT_EQ(expected_status, rv);
4010}
4011
4012void HttpNetworkTransactionTest::ConnectStatusHelper(
4013    const MockRead& status) {
4014  ConnectStatusHelperWithExpectedStatus(
4015      status, ERR_TUNNEL_CONNECTION_FAILED);
4016}
4017
4018TEST_P(HttpNetworkTransactionTest, ConnectStatus100) {
4019  ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
4020}
4021
4022TEST_P(HttpNetworkTransactionTest, ConnectStatus101) {
4023  ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
4024}
4025
4026TEST_P(HttpNetworkTransactionTest, ConnectStatus201) {
4027  ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
4028}
4029
4030TEST_P(HttpNetworkTransactionTest, ConnectStatus202) {
4031  ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
4032}
4033
4034TEST_P(HttpNetworkTransactionTest, ConnectStatus203) {
4035  ConnectStatusHelper(
4036      MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
4037}
4038
4039TEST_P(HttpNetworkTransactionTest, ConnectStatus204) {
4040  ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
4041}
4042
4043TEST_P(HttpNetworkTransactionTest, ConnectStatus205) {
4044  ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
4045}
4046
4047TEST_P(HttpNetworkTransactionTest, ConnectStatus206) {
4048  ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
4049}
4050
4051TEST_P(HttpNetworkTransactionTest, ConnectStatus300) {
4052  ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
4053}
4054
4055TEST_P(HttpNetworkTransactionTest, ConnectStatus301) {
4056  ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
4057}
4058
4059TEST_P(HttpNetworkTransactionTest, ConnectStatus302) {
4060  ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
4061}
4062
4063TEST_P(HttpNetworkTransactionTest, ConnectStatus303) {
4064  ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
4065}
4066
4067TEST_P(HttpNetworkTransactionTest, ConnectStatus304) {
4068  ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
4069}
4070
4071TEST_P(HttpNetworkTransactionTest, ConnectStatus305) {
4072  ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
4073}
4074
4075TEST_P(HttpNetworkTransactionTest, ConnectStatus306) {
4076  ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
4077}
4078
4079TEST_P(HttpNetworkTransactionTest, ConnectStatus307) {
4080  ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
4081}
4082
4083TEST_P(HttpNetworkTransactionTest, ConnectStatus308) {
4084  ConnectStatusHelper(MockRead("HTTP/1.1 308 Permanent Redirect\r\n"));
4085}
4086
4087TEST_P(HttpNetworkTransactionTest, ConnectStatus400) {
4088  ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
4089}
4090
4091TEST_P(HttpNetworkTransactionTest, ConnectStatus401) {
4092  ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
4093}
4094
4095TEST_P(HttpNetworkTransactionTest, ConnectStatus402) {
4096  ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
4097}
4098
4099TEST_P(HttpNetworkTransactionTest, ConnectStatus403) {
4100  ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
4101}
4102
4103TEST_P(HttpNetworkTransactionTest, ConnectStatus404) {
4104  ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
4105}
4106
4107TEST_P(HttpNetworkTransactionTest, ConnectStatus405) {
4108  ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
4109}
4110
4111TEST_P(HttpNetworkTransactionTest, ConnectStatus406) {
4112  ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
4113}
4114
4115TEST_P(HttpNetworkTransactionTest, ConnectStatus407) {
4116  ConnectStatusHelperWithExpectedStatus(
4117      MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4118      ERR_PROXY_AUTH_UNSUPPORTED);
4119}
4120
4121TEST_P(HttpNetworkTransactionTest, ConnectStatus408) {
4122  ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
4123}
4124
4125TEST_P(HttpNetworkTransactionTest, ConnectStatus409) {
4126  ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
4127}
4128
4129TEST_P(HttpNetworkTransactionTest, ConnectStatus410) {
4130  ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
4131}
4132
4133TEST_P(HttpNetworkTransactionTest, ConnectStatus411) {
4134  ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
4135}
4136
4137TEST_P(HttpNetworkTransactionTest, ConnectStatus412) {
4138  ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
4139}
4140
4141TEST_P(HttpNetworkTransactionTest, ConnectStatus413) {
4142  ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
4143}
4144
4145TEST_P(HttpNetworkTransactionTest, ConnectStatus414) {
4146  ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
4147}
4148
4149TEST_P(HttpNetworkTransactionTest, ConnectStatus415) {
4150  ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
4151}
4152
4153TEST_P(HttpNetworkTransactionTest, ConnectStatus416) {
4154  ConnectStatusHelper(
4155      MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
4156}
4157
4158TEST_P(HttpNetworkTransactionTest, ConnectStatus417) {
4159  ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
4160}
4161
4162TEST_P(HttpNetworkTransactionTest, ConnectStatus500) {
4163  ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
4164}
4165
4166TEST_P(HttpNetworkTransactionTest, ConnectStatus501) {
4167  ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
4168}
4169
4170TEST_P(HttpNetworkTransactionTest, ConnectStatus502) {
4171  ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
4172}
4173
4174TEST_P(HttpNetworkTransactionTest, ConnectStatus503) {
4175  ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
4176}
4177
4178TEST_P(HttpNetworkTransactionTest, ConnectStatus504) {
4179  ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
4180}
4181
4182TEST_P(HttpNetworkTransactionTest, ConnectStatus505) {
4183  ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
4184}
4185
4186// Test the flow when both the proxy server AND origin server require
4187// authentication. Again, this uses basic auth for both since that is
4188// the simplest to mock.
4189TEST_P(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
4190  HttpRequestInfo request;
4191  request.method = "GET";
4192  request.url = GURL("http://www.google.com/");
4193  request.load_flags = 0;
4194
4195  // Configure against proxy server "myproxy:70".
4196  session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
4197  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4198
4199  scoped_ptr<HttpTransaction> trans(
4200      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4201
4202  MockWrite data_writes1[] = {
4203    MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
4204              "Host: www.google.com\r\n"
4205              "Proxy-Connection: keep-alive\r\n\r\n"),
4206  };
4207
4208  MockRead data_reads1[] = {
4209    MockRead("HTTP/1.0 407 Unauthorized\r\n"),
4210    // Give a couple authenticate options (only the middle one is actually
4211    // supported).
4212    MockRead("Proxy-Authenticate: Basic invalid\r\n"),  // Malformed.
4213    MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4214    MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
4215    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4216    // Large content-length -- won't matter, as connection will be reset.
4217    MockRead("Content-Length: 10000\r\n\r\n"),
4218    MockRead(SYNCHRONOUS, ERR_FAILED),
4219  };
4220
4221  // After calling trans->RestartWithAuth() the first time, this is the
4222  // request we should be issuing -- the final header line contains the
4223  // proxy's credentials.
4224  MockWrite data_writes2[] = {
4225    MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
4226              "Host: www.google.com\r\n"
4227              "Proxy-Connection: keep-alive\r\n"
4228              "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4229  };
4230
4231  // Now the proxy server lets the request pass through to origin server.
4232  // The origin server responds with a 401.
4233  MockRead data_reads2[] = {
4234    MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4235    // Note: We are using the same realm-name as the proxy server. This is
4236    // completely valid, as realms are unique across hosts.
4237    MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4238    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4239    MockRead("Content-Length: 2000\r\n\r\n"),
4240    MockRead(SYNCHRONOUS, ERR_FAILED),  // Won't be reached.
4241  };
4242
4243  // After calling trans->RestartWithAuth() the second time, we should send
4244  // the credentials for both the proxy and origin server.
4245  MockWrite data_writes3[] = {
4246    MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
4247              "Host: www.google.com\r\n"
4248              "Proxy-Connection: keep-alive\r\n"
4249              "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
4250              "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
4251  };
4252
4253  // Lastly we get the desired content.
4254  MockRead data_reads3[] = {
4255    MockRead("HTTP/1.0 200 OK\r\n"),
4256    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4257    MockRead("Content-Length: 100\r\n\r\n"),
4258    MockRead(SYNCHRONOUS, OK),
4259  };
4260
4261  StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4262                                 data_writes1, arraysize(data_writes1));
4263  StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4264                                 data_writes2, arraysize(data_writes2));
4265  StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
4266                                 data_writes3, arraysize(data_writes3));
4267  session_deps_.socket_factory->AddSocketDataProvider(&data1);
4268  session_deps_.socket_factory->AddSocketDataProvider(&data2);
4269  session_deps_.socket_factory->AddSocketDataProvider(&data3);
4270
4271  TestCompletionCallback callback1;
4272
4273  int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
4274  EXPECT_EQ(ERR_IO_PENDING, rv);
4275
4276  rv = callback1.WaitForResult();
4277  EXPECT_EQ(OK, rv);
4278
4279  const HttpResponseInfo* response = trans->GetResponseInfo();
4280  ASSERT_TRUE(response != NULL);
4281  EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
4282
4283  TestCompletionCallback callback2;
4284
4285  rv = trans->RestartWithAuth(
4286      AuthCredentials(kFoo, kBar), callback2.callback());
4287  EXPECT_EQ(ERR_IO_PENDING, rv);
4288
4289  rv = callback2.WaitForResult();
4290  EXPECT_EQ(OK, rv);
4291
4292  response = trans->GetResponseInfo();
4293  ASSERT_TRUE(response != NULL);
4294  EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
4295
4296  TestCompletionCallback callback3;
4297
4298  rv = trans->RestartWithAuth(
4299      AuthCredentials(kFoo2, kBar2), callback3.callback());
4300  EXPECT_EQ(ERR_IO_PENDING, rv);
4301
4302  rv = callback3.WaitForResult();
4303  EXPECT_EQ(OK, rv);
4304
4305  response = trans->GetResponseInfo();
4306  EXPECT_TRUE(response->auth_challenge.get() == NULL);
4307  EXPECT_EQ(100, response->headers->GetContentLength());
4308}
4309
4310// For the NTLM implementation using SSPI, we skip the NTLM tests since we
4311// can't hook into its internals to cause it to generate predictable NTLM
4312// authorization headers.
4313#if defined(NTLM_PORTABLE)
4314// The NTLM authentication unit tests were generated by capturing the HTTP
4315// requests and responses using Fiddler 2 and inspecting the generated random
4316// bytes in the debugger.
4317
4318// Enter the correct password and authenticate successfully.
4319TEST_P(HttpNetworkTransactionTest, NTLMAuth1) {
4320  HttpRequestInfo request;
4321  request.method = "GET";
4322  request.url = GURL("http://172.22.68.17/kids/login.aspx");
4323
4324  // Ensure load is not disrupted by flags which suppress behaviour specific
4325  // to other auth schemes.
4326  request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
4327
4328  HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom1,
4329                                                    MockGetHostName);
4330  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4331
4332  MockWrite data_writes1[] = {
4333    MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4334              "Host: 172.22.68.17\r\n"
4335              "Connection: keep-alive\r\n\r\n"),
4336  };
4337
4338  MockRead data_reads1[] = {
4339    MockRead("HTTP/1.1 401 Access Denied\r\n"),
4340    // Negotiate and NTLM are often requested together.  However, we only want
4341    // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
4342    // the header that requests Negotiate for this test.
4343    MockRead("WWW-Authenticate: NTLM\r\n"),
4344    MockRead("Connection: close\r\n"),
4345    MockRead("Content-Length: 42\r\n"),
4346    MockRead("Content-Type: text/html\r\n\r\n"),
4347    // Missing content -- won't matter, as connection will be reset.
4348    MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
4349  };
4350
4351  MockWrite data_writes2[] = {
4352    // After restarting with a null identity, this is the
4353    // request we should be issuing -- the final header line contains a Type
4354    // 1 message.
4355    MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4356              "Host: 172.22.68.17\r\n"
4357              "Connection: keep-alive\r\n"
4358              "Authorization: NTLM "
4359              "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4360
4361    // After calling trans->RestartWithAuth(), we should send a Type 3 message
4362    // (the credentials for the origin server).  The second request continues
4363    // on the same connection.
4364    MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4365              "Host: 172.22.68.17\r\n"
4366              "Connection: keep-alive\r\n"
4367              "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4368              "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4369              "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
4370              "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
4371              "ahlhx5I=\r\n\r\n"),
4372  };
4373
4374  MockRead data_reads2[] = {
4375    // The origin server responds with a Type 2 message.
4376    MockRead("HTTP/1.1 401 Access Denied\r\n"),
4377    MockRead("WWW-Authenticate: NTLM "
4378             "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
4379             "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4380             "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4381             "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4382             "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4383             "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4384             "BtAAAAAAA=\r\n"),
4385    MockRead("Content-Length: 42\r\n"),
4386    MockRead("Content-Type: text/html\r\n\r\n"),
4387    MockRead("You are not authorized to view this page\r\n"),
4388
4389    // Lastly we get the desired content.
4390    MockRead("HTTP/1.1 200 OK\r\n"),
4391    MockRead("Content-Type: text/html; charset=utf-8\r\n"),
4392    MockRead("Content-Length: 13\r\n\r\n"),
4393    MockRead("Please Login\r\n"),
4394    MockRead(SYNCHRONOUS, OK),
4395  };
4396
4397  StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4398                                 data_writes1, arraysize(data_writes1));
4399  StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4400                                 data_writes2, arraysize(data_writes2));
4401  session_deps_.socket_factory->AddSocketDataProvider(&data1);
4402  session_deps_.socket_factory->AddSocketDataProvider(&data2);
4403
4404  TestCompletionCallback callback1;
4405
4406  scoped_ptr<HttpTransaction> trans(
4407      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4408
4409  int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
4410  EXPECT_EQ(ERR_IO_PENDING, rv);
4411
4412  rv = callback1.WaitForResult();
4413  EXPECT_EQ(OK, rv);
4414
4415  EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4416
4417  const HttpResponseInfo* response = trans->GetResponseInfo();
4418  ASSERT_FALSE(response == NULL);
4419  EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
4420
4421  TestCompletionCallback callback2;
4422
4423  rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kTestingNTLM),
4424                              callback2.callback());
4425  EXPECT_EQ(ERR_IO_PENDING, rv);
4426
4427  rv = callback2.WaitForResult();
4428  EXPECT_EQ(OK, rv);
4429
4430  EXPECT_TRUE(trans->IsReadyToRestartForAuth());
4431
4432  response = trans->GetResponseInfo();
4433  ASSERT_TRUE(response != NULL);
4434  EXPECT_TRUE(response->auth_challenge.get() == NULL);
4435
4436  TestCompletionCallback callback3;
4437
4438  rv = trans->RestartWithAuth(AuthCredentials(), callback3.callback());
4439  EXPECT_EQ(ERR_IO_PENDING, rv);
4440
4441  rv = callback3.WaitForResult();
4442  EXPECT_EQ(OK, rv);
4443
4444  response = trans->GetResponseInfo();
4445  ASSERT_TRUE(response != NULL);
4446  EXPECT_TRUE(response->auth_challenge.get() == NULL);
4447  EXPECT_EQ(13, response->headers->GetContentLength());
4448}
4449
4450// Enter a wrong password, and then the correct one.
4451TEST_P(HttpNetworkTransactionTest, NTLMAuth2) {
4452  HttpRequestInfo request;
4453  request.method = "GET";
4454  request.url = GURL("http://172.22.68.17/kids/login.aspx");
4455  request.load_flags = 0;
4456
4457  HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom2,
4458                                                    MockGetHostName);
4459  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4460
4461  MockWrite data_writes1[] = {
4462    MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4463              "Host: 172.22.68.17\r\n"
4464              "Connection: keep-alive\r\n\r\n"),
4465  };
4466
4467  MockRead data_reads1[] = {
4468    MockRead("HTTP/1.1 401 Access Denied\r\n"),
4469    // Negotiate and NTLM are often requested together.  However, we only want
4470    // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
4471    // the header that requests Negotiate for this test.
4472    MockRead("WWW-Authenticate: NTLM\r\n"),
4473    MockRead("Connection: close\r\n"),
4474    MockRead("Content-Length: 42\r\n"),
4475    MockRead("Content-Type: text/html\r\n\r\n"),
4476    // Missing content -- won't matter, as connection will be reset.
4477    MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
4478  };
4479
4480  MockWrite data_writes2[] = {
4481    // After restarting with a null identity, this is the
4482    // request we should be issuing -- the final header line contains a Type
4483    // 1 message.
4484    MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4485              "Host: 172.22.68.17\r\n"
4486              "Connection: keep-alive\r\n"
4487              "Authorization: NTLM "
4488              "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4489
4490    // After calling trans->RestartWithAuth(), we should send a Type 3 message
4491    // (the credentials for the origin server).  The second request continues
4492    // on the same connection.
4493    MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4494              "Host: 172.22.68.17\r\n"
4495              "Connection: keep-alive\r\n"
4496              "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4497              "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4498              "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
4499              "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
4500              "4Ww7b7E=\r\n\r\n"),
4501  };
4502
4503  MockRead data_reads2[] = {
4504    // The origin server responds with a Type 2 message.
4505    MockRead("HTTP/1.1 401 Access Denied\r\n"),
4506    MockRead("WWW-Authenticate: NTLM "
4507             "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
4508             "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4509             "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4510             "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4511             "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4512             "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4513             "BtAAAAAAA=\r\n"),
4514    MockRead("Content-Length: 42\r\n"),
4515    MockRead("Content-Type: text/html\r\n\r\n"),
4516    MockRead("You are not authorized to view this page\r\n"),
4517
4518    // Wrong password.
4519    MockRead("HTTP/1.1 401 Access Denied\r\n"),
4520    MockRead("WWW-Authenticate: NTLM\r\n"),
4521    MockRead("Connection: close\r\n"),
4522    MockRead("Content-Length: 42\r\n"),
4523    MockRead("Content-Type: text/html\r\n\r\n"),
4524    // Missing content -- won't matter, as connection will be reset.
4525    MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
4526  };
4527
4528  MockWrite data_writes3[] = {
4529    // After restarting with a null identity, this is the
4530    // request we should be issuing -- the final header line contains a Type
4531    // 1 message.
4532    MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4533              "Host: 172.22.68.17\r\n"
4534              "Connection: keep-alive\r\n"
4535              "Authorization: NTLM "
4536              "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4537
4538    // After calling trans->RestartWithAuth(), we should send a Type 3 message
4539    // (the credentials for the origin server).  The second request continues
4540    // on the same connection.
4541    MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4542              "Host: 172.22.68.17\r\n"
4543              "Connection: keep-alive\r\n"
4544              "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4545              "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4546              "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
4547              "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
4548              "+4MUm7c=\r\n\r\n"),
4549  };
4550
4551  MockRead data_reads3[] = {
4552    // The origin server responds with a Type 2 message.
4553    MockRead("HTTP/1.1 401 Access Denied\r\n"),
4554    MockRead("WWW-Authenticate: NTLM "
4555             "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
4556             "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4557             "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4558             "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4559             "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4560             "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4561             "BtAAAAAAA=\r\n"),
4562    MockRead("Content-Length: 42\r\n"),
4563    MockRead("Content-Type: text/html\r\n\r\n"),
4564    MockRead("You are not authorized to view this page\r\n"),
4565
4566    // Lastly we get the desired content.
4567    MockRead("HTTP/1.1 200 OK\r\n"),
4568    MockRead("Content-Type: text/html; charset=utf-8\r\n"),
4569    MockRead("Content-Length: 13\r\n\r\n"),
4570    MockRead("Please Login\r\n"),
4571    MockRead(SYNCHRONOUS, OK),
4572  };
4573
4574  StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4575                                 data_writes1, arraysize(data_writes1));
4576  StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4577                                 data_writes2, arraysize(data_writes2));
4578  StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
4579                                 data_writes3, arraysize(data_writes3));
4580  session_deps_.socket_factory->AddSocketDataProvider(&data1);
4581  session_deps_.socket_factory->AddSocketDataProvider(&data2);
4582  session_deps_.socket_factory->AddSocketDataProvider(&data3);
4583
4584  TestCompletionCallback callback1;
4585
4586  scoped_ptr<HttpTransaction> trans(
4587      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4588
4589  int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
4590  EXPECT_EQ(ERR_IO_PENDING, rv);
4591
4592  rv = callback1.WaitForResult();
4593  EXPECT_EQ(OK, rv);
4594
4595  EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4596
4597  const HttpResponseInfo* response = trans->GetResponseInfo();
4598  ASSERT_TRUE(response != NULL);
4599  EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
4600
4601  TestCompletionCallback callback2;
4602
4603  // Enter the wrong password.
4604  rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kWrongPassword),
4605                              callback2.callback());
4606  EXPECT_EQ(ERR_IO_PENDING, rv);
4607
4608  rv = callback2.WaitForResult();
4609  EXPECT_EQ(OK, rv);
4610
4611  EXPECT_TRUE(trans->IsReadyToRestartForAuth());
4612  TestCompletionCallback callback3;
4613  rv = trans->RestartWithAuth(AuthCredentials(), callback3.callback());
4614  EXPECT_EQ(ERR_IO_PENDING, rv);
4615  rv = callback3.WaitForResult();
4616  EXPECT_EQ(OK, rv);
4617  EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4618
4619  response = trans->GetResponseInfo();
4620  ASSERT_FALSE(response == NULL);
4621  EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
4622
4623  TestCompletionCallback callback4;
4624
4625  // Now enter the right password.
4626  rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kTestingNTLM),
4627                              callback4.callback());
4628  EXPECT_EQ(ERR_IO_PENDING, rv);
4629
4630  rv = callback4.WaitForResult();
4631  EXPECT_EQ(OK, rv);
4632
4633  EXPECT_TRUE(trans->IsReadyToRestartForAuth());
4634
4635  TestCompletionCallback callback5;
4636
4637  // One more roundtrip
4638  rv = trans->RestartWithAuth(AuthCredentials(), callback5.callback());
4639  EXPECT_EQ(ERR_IO_PENDING, rv);
4640
4641  rv = callback5.WaitForResult();
4642  EXPECT_EQ(OK, rv);
4643
4644  response = trans->GetResponseInfo();
4645  EXPECT_TRUE(response->auth_challenge.get() == NULL);
4646  EXPECT_EQ(13, response->headers->GetContentLength());
4647}
4648#endif  // NTLM_PORTABLE
4649
4650// Test reading a server response which has only headers, and no body.
4651// After some maximum number of bytes is consumed, the transaction should
4652// fail with ERR_RESPONSE_HEADERS_TOO_BIG.
4653TEST_P(HttpNetworkTransactionTest, LargeHeadersNoBody) {
4654  HttpRequestInfo request;
4655  request.method = "GET";
4656  request.url = GURL("http://www.google.com/");
4657  request.load_flags = 0;
4658
4659  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4660  scoped_ptr<HttpTransaction> trans(
4661      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4662
4663  // Respond with 300 kb of headers (we should fail after 256 kb).
4664  std::string large_headers_string;
4665  FillLargeHeadersString(&large_headers_string, 300 * 1024);
4666
4667  MockRead data_reads[] = {
4668    MockRead("HTTP/1.0 200 OK\r\n"),
4669    MockRead(ASYNC, large_headers_string.data(), large_headers_string.size()),
4670    MockRead("\r\nBODY"),
4671    MockRead(SYNCHRONOUS, OK),
4672  };
4673  StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
4674  session_deps_.socket_factory->AddSocketDataProvider(&data);
4675
4676  TestCompletionCallback callback;
4677
4678  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
4679  EXPECT_EQ(ERR_IO_PENDING, rv);
4680
4681  rv = callback.WaitForResult();
4682  EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG, rv);
4683
4684  const HttpResponseInfo* response = trans->GetResponseInfo();
4685  EXPECT_TRUE(response == NULL);
4686}
4687
4688// Make sure that we don't try to reuse a TCPClientSocket when failing to
4689// establish tunnel.
4690// http://code.google.com/p/chromium/issues/detail?id=3772
4691TEST_P(HttpNetworkTransactionTest,
4692       DontRecycleTransportSocketForSSLTunnel) {
4693  HttpRequestInfo request;
4694  request.method = "GET";
4695  request.url = GURL("https://www.google.com/");
4696  request.load_flags = 0;
4697
4698  // Configure against proxy server "myproxy:70".
4699  session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
4700
4701  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4702
4703  scoped_ptr<HttpTransaction> trans(
4704      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4705
4706  // Since we have proxy, should try to establish tunnel.
4707  MockWrite data_writes1[] = {
4708    MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4709              "Host: www.google.com\r\n"
4710              "Proxy-Connection: keep-alive\r\n\r\n"),
4711  };
4712
4713  // The proxy responds to the connect with a 404, using a persistent
4714  // connection. Usually a proxy would return 501 (not implemented),
4715  // or 200 (tunnel established).
4716  MockRead data_reads1[] = {
4717    MockRead("HTTP/1.1 404 Not Found\r\n"),
4718    MockRead("Content-Length: 10\r\n\r\n"),
4719    MockRead(SYNCHRONOUS, ERR_UNEXPECTED),  // Should not be reached.
4720  };
4721
4722  StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4723                                 data_writes1, arraysize(data_writes1));
4724  session_deps_.socket_factory->AddSocketDataProvider(&data1);
4725
4726  TestCompletionCallback callback1;
4727
4728  int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
4729  EXPECT_EQ(ERR_IO_PENDING, rv);
4730
4731  rv = callback1.WaitForResult();
4732  EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
4733
4734  const HttpResponseInfo* response = trans->GetResponseInfo();
4735  EXPECT_TRUE(response == NULL);
4736
4737  // Empty the current queue.  This is necessary because idle sockets are
4738  // added to the connection pool asynchronously with a PostTask.
4739  base::MessageLoop::current()->RunUntilIdle();
4740
4741  // We now check to make sure the TCPClientSocket was not added back to
4742  // the pool.
4743  EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
4744  trans.reset();
4745  base::MessageLoop::current()->RunUntilIdle();
4746  // Make sure that the socket didn't get recycled after calling the destructor.
4747  EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
4748}
4749
4750// Make sure that we recycle a socket after reading all of the response body.
4751TEST_P(HttpNetworkTransactionTest, RecycleSocket) {
4752  HttpRequestInfo request;
4753  request.method = "GET";
4754  request.url = GURL("http://www.google.com/");
4755  request.load_flags = 0;
4756
4757  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4758
4759  scoped_ptr<HttpTransaction> trans(
4760      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4761
4762  MockRead data_reads[] = {
4763    // A part of the response body is received with the response headers.
4764    MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
4765    // The rest of the response body is received in two parts.
4766    MockRead("lo"),
4767    MockRead(" world"),
4768    MockRead("junk"),  // Should not be read!!
4769    MockRead(SYNCHRONOUS, OK),
4770  };
4771
4772  StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
4773  session_deps_.socket_factory->AddSocketDataProvider(&data);
4774
4775  TestCompletionCallback callback;
4776
4777  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
4778  EXPECT_EQ(ERR_IO_PENDING, rv);
4779
4780  rv = callback.WaitForResult();
4781  EXPECT_EQ(OK, rv);
4782
4783  const HttpResponseInfo* response = trans->GetResponseInfo();
4784  ASSERT_TRUE(response != NULL);
4785
4786  EXPECT_TRUE(response->headers.get() != NULL);
4787  std::string status_line = response->headers->GetStatusLine();
4788  EXPECT_EQ("HTTP/1.1 200 OK", status_line);
4789
4790  EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
4791
4792  std::string response_data;
4793  rv = ReadTransaction(trans.get(), &response_data);
4794  EXPECT_EQ(OK, rv);
4795  EXPECT_EQ("hello world", response_data);
4796
4797  // Empty the current queue.  This is necessary because idle sockets are
4798  // added to the connection pool asynchronously with a PostTask.
4799  base::MessageLoop::current()->RunUntilIdle();
4800
4801  // We now check to make sure the socket was added back to the pool.
4802  EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
4803}
4804
4805// Make sure that we recycle a SSL socket after reading all of the response
4806// body.
4807TEST_P(HttpNetworkTransactionTest, RecycleSSLSocket) {
4808  HttpRequestInfo request;
4809  request.method = "GET";
4810  request.url = GURL("https://www.google.com/");
4811  request.load_flags = 0;
4812
4813  MockWrite data_writes[] = {
4814    MockWrite("GET / HTTP/1.1\r\n"
4815              "Host: www.google.com\r\n"
4816              "Connection: keep-alive\r\n\r\n"),
4817  };
4818
4819  MockRead data_reads[] = {
4820    MockRead("HTTP/1.1 200 OK\r\n"),
4821    MockRead("Content-Length: 11\r\n\r\n"),
4822    MockRead("hello world"),
4823    MockRead(SYNCHRONOUS, OK),
4824  };
4825
4826  SSLSocketDataProvider ssl(ASYNC, OK);
4827  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
4828
4829  StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4830                                data_writes, arraysize(data_writes));
4831  session_deps_.socket_factory->AddSocketDataProvider(&data);
4832
4833  TestCompletionCallback callback;
4834
4835  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4836  scoped_ptr<HttpTransaction> trans(
4837      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4838
4839  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
4840
4841  EXPECT_EQ(ERR_IO_PENDING, rv);
4842  EXPECT_EQ(OK, callback.WaitForResult());
4843
4844  const HttpResponseInfo* response = trans->GetResponseInfo();
4845  ASSERT_TRUE(response != NULL);
4846  ASSERT_TRUE(response->headers.get() != NULL);
4847  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4848
4849  EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
4850
4851  std::string response_data;
4852  rv = ReadTransaction(trans.get(), &response_data);
4853  EXPECT_EQ(OK, rv);
4854  EXPECT_EQ("hello world", response_data);
4855
4856  // Empty the current queue.  This is necessary because idle sockets are
4857  // added to the connection pool asynchronously with a PostTask.
4858  base::MessageLoop::current()->RunUntilIdle();
4859
4860  // We now check to make sure the socket was added back to the pool.
4861  EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
4862}
4863
4864// Grab a SSL socket, use it, and put it back into the pool.  Then, reuse it
4865// from the pool and make sure that we recover okay.
4866TEST_P(HttpNetworkTransactionTest, RecycleDeadSSLSocket) {
4867  HttpRequestInfo request;
4868  request.method = "GET";
4869  request.url = GURL("https://www.google.com/");
4870  request.load_flags = 0;
4871
4872  MockWrite data_writes[] = {
4873    MockWrite("GET / HTTP/1.1\r\n"
4874              "Host: www.google.com\r\n"
4875              "Connection: keep-alive\r\n\r\n"),
4876    MockWrite("GET / HTTP/1.1\r\n"
4877              "Host: www.google.com\r\n"
4878              "Connection: keep-alive\r\n\r\n"),
4879  };
4880
4881  MockRead data_reads[] = {
4882    MockRead("HTTP/1.1 200 OK\r\n"),
4883    MockRead("Content-Length: 11\r\n\r\n"),
4884    MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
4885    MockRead("hello world"),