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