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
53namespace {
54
55const string16 kBar(ASCIIToUTF16("bar"));
56const string16 kBar2(ASCIIToUTF16("bar2"));
57const string16 kBar3(ASCIIToUTF16("bar3"));
58const string16 kBaz(ASCIIToUTF16("baz"));
59const string16 kFirst(ASCIIToUTF16("first"));
60const string16 kFoo(ASCIIToUTF16("foo"));
61const string16 kFoo2(ASCIIToUTF16("foo2"));
62const string16 kFoo3(ASCIIToUTF16("foo3"));
63const string16 kFou(ASCIIToUTF16("fou"));
64const string16 kSecond(ASCIIToUTF16("second"));
65const string16 kTestingNTLM(ASCIIToUTF16("testing-ntlm"));
66const string16 kWrongPassword(ASCIIToUTF16("wrongpassword"));
67
68}  // namespace
69
70namespace net {
71
72// Helper to manage the lifetimes of the dependencies for a
73// HttpNetworkTransaction.
74struct 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
104HttpNetworkSession* 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
117class 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.
212void 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.
228void 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
239void 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
251std::string MockGetHostName() {
252  return "WTC-WIN7";
253}
254
255template<typename ParentPool>
256class 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
298typedef CaptureGroupNameSocketPool<TransportClientSocketPool>
299CaptureGroupNameTransportSocketPool;
300typedef CaptureGroupNameSocketPool<HttpProxyClientSocketPool>
301CaptureGroupNameHttpProxySocketPool;
302typedef CaptureGroupNameSocketPool<SOCKSClientSocketPool>
303CaptureGroupNameSOCKSSocketPool;
304typedef CaptureGroupNameSocketPool<SSLClientSocketPool>
305CaptureGroupNameSSLSocketPool;
306
307template<typename ParentPool>
308CaptureGroupNameSocketPool<ParentPool>::CaptureGroupNameSocketPool(
309    HostResolver* host_resolver,
310    CertVerifier* /* cert_verifier */)
311    : ParentPool(0, 0, NULL, host_resolver, NULL, NULL) {}
312
313template<>
314CaptureGroupNameHttpProxySocketPool::CaptureGroupNameSocketPool(
315    HostResolver* host_resolver,
316    CertVerifier* /* cert_verifier */)
317    : HttpProxyClientSocketPool(0, 0, NULL, host_resolver, NULL, NULL, NULL) {}
318
319template<>
320CaptureGroupNameSSLSocketPool::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.
330static const char kExpectedNPNString[] = "\x08http/1.1\x06spdy/2";
331
332// This is the expected return from a current server advertising SPDY.
333static const char kAlternateProtocolHttpHeader[] =
334    "Alternate-Protocol: 443:npn-spdy/2\r\n\r\n";
335
336TEST_F(HttpNetworkTransactionTest, Basic) {
337  SessionDependencies session_deps;
338  scoped_ptr<HttpTransaction> trans(
339      new HttpNetworkTransaction(CreateSession(&session_deps)));
340}
341
342TEST_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.
356TEST_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.
369TEST_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.
382TEST_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.
395TEST_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.
408TEST_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.
425TEST_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.
440TEST_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.)
455TEST_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
474TEST_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
486TEST_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
501TEST_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
547TEST_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).
570TEST_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
630TEST_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
677TEST_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.
721TEST_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
760TEST_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
791TEST_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.
818void 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
872TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
873  MockRead read_failure(true, ERR_CONNECTION_RESET);
874  KeepAliveConnectionResendRequestTest(read_failure);
875}
876
877TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
878  MockRead read_failure(false, OK);  // EOF
879  KeepAliveConnectionResendRequestTest(read_failure);
880}
881
882TEST_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)
922TEST_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.
936TEST_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).
1031TEST_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
1116TEST_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.
1159TEST_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.
1243TEST_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.
1324TEST_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.
1413TEST_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.
1504TEST_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.
1614TEST_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.
1728TEST_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.
1786TEST_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.
1831TEST_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.
1888TEST_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.
1942TEST_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.
2001TEST_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.
2108TEST_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.
2186TEST_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.
2260TEST_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
2321TEST_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
2412void 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
2453void HttpNetworkTransactionTest::ConnectStatusHelper(const MockRead& status) {
2454  ConnectStatusHelperWithExpectedStatus(
2455      status, ERR_TUNNEL_CONNECTION_FAILED);
2456}
2457
2458TEST_F(HttpNetworkTransactionTest, ConnectStatus100) {
2459  ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
2460}
2461
2462TEST_F(HttpNetworkTransactionTest, ConnectStatus101) {
2463  ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
2464}
2465
2466TEST_F(HttpNetworkTransactionTest, ConnectStatus201) {
2467  ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
2468}
2469
2470TEST_F(HttpNetworkTransactionTest, ConnectStatus202) {
2471  ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
2472}
2473
2474TEST_F(HttpNetworkTransactionTest, ConnectStatus203) {
2475  ConnectStatusHelper(
2476      MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
2477}
2478
2479TEST_F(HttpNetworkTransactionTest, ConnectStatus204) {
2480  ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
2481}
2482
2483TEST_F(HttpNetworkTransactionTest, ConnectStatus205) {
2484  ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
2485}
2486
2487TEST_F(HttpNetworkTransactionTest, ConnectStatus206) {
2488  ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
2489}
2490
2491TEST_F(HttpNetworkTransactionTest, ConnectStatus300) {
2492  ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
2493}
2494
2495TEST_F(HttpNetworkTransactionTest, ConnectStatus301) {
2496  ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
2497}
2498
2499TEST_F(HttpNetworkTransactionTest, ConnectStatus302) {
2500  ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
2501}
2502
2503TEST_F(HttpNetworkTransactionTest, ConnectStatus303) {
2504  ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
2505}
2506
2507TEST_F(HttpNetworkTransactionTest, ConnectStatus304) {
2508  ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
2509}
2510
2511TEST_F(HttpNetworkTransactionTest, ConnectStatus305) {
2512  ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
2513}
2514
2515TEST_F(HttpNetworkTransactionTest, ConnectStatus306) {
2516  ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
2517}
2518
2519TEST_F(HttpNetworkTransactionTest, ConnectStatus307) {
2520  ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
2521}
2522
2523TEST_F(HttpNetworkTransactionTest, ConnectStatus400) {
2524  ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
2525}
2526
2527TEST_F(HttpNetworkTransactionTest, ConnectStatus401) {
2528  ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
2529}
2530
2531TEST_F(HttpNetworkTransactionTest, ConnectStatus402) {
2532  ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
2533}
2534
2535TEST_F(HttpNetworkTransactionTest, ConnectStatus403) {
2536  ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
2537}
2538
2539TEST_F(HttpNetworkTransactionTest, ConnectStatus404) {
2540  ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
2541}
2542
2543TEST_F(HttpNetworkTransactionTest, ConnectStatus405) {
2544  ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
2545}
2546
2547TEST_F(HttpNetworkTransactionTest, ConnectStatus406) {
2548  ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
2549}
2550
2551TEST_F(HttpNetworkTransactionTest, ConnectStatus407) {
2552  ConnectStatusHelperWithExpectedStatus(
2553      MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2554      ERR_PROXY_AUTH_UNSUPPORTED);
2555}
2556
2557TEST_F(HttpNetworkTransactionTest, ConnectStatus408) {
2558  ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
2559}
2560
2561TEST_F(HttpNetworkTransactionTest, ConnectStatus409) {
2562  ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
2563}
2564
2565TEST_F(HttpNetworkTransactionTest, ConnectStatus410) {
2566  ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
2567}
2568
2569TEST_F(HttpNetworkTransactionTest, ConnectStatus411) {
2570  ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
2571}
2572
2573TEST_F(HttpNetworkTransactionTest, ConnectStatus412) {
2574  ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
2575}
2576
2577TEST_F(HttpNetworkTransactionTest, ConnectStatus413) {
2578  ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
2579}
2580
2581TEST_F(HttpNetworkTransactionTest, ConnectStatus414) {
2582  ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
2583}
2584
2585TEST_F(HttpNetworkTransactionTest, ConnectStatus415) {
2586  ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
2587}
2588
2589TEST_F(HttpNetworkTransactionTest, ConnectStatus416) {
2590  ConnectStatusHelper(
2591      MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
2592}
2593
2594TEST_F(HttpNetworkTransactionTest, ConnectStatus417) {
2595  ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
2596}
2597
2598TEST_F(HttpNetworkTransactionTest, ConnectStatus500) {
2599  ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
2600}
2601
2602TEST_F(HttpNetworkTransactionTest, ConnectStatus501) {
2603  ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
2604}
2605
2606TEST_F(HttpNetworkTransactionTest, ConnectStatus502) {
2607  ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
2608}
2609
2610TEST_F(HttpNetworkTransactionTest, ConnectStatus503) {
2611  ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
2612}
2613
2614TEST_F(HttpNetworkTransactionTest, ConnectStatus504) {
2615  ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
2616}
2617
2618TEST_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.
2625TEST_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.
2762TEST_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.
2898TEST_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.
3110TEST_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
3148TEST_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.
3206TEST_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.
3262TEST_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.
3321TEST_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
3416TEST_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
3471TEST_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.
3561TEST_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.
3643TEST_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.
3755TEST_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.
4148TEST_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.
4287TEST_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
4330TEST_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
4386TEST_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
4464TEST_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
4519TEST_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
4569TEST_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
4630TEST_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
4685TEST_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
4752TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaHttpsProxy) {
4753  SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
4754
4755  HttpRequestInfo request;
4756  request.method = "GET";
4757  request.url = GURL("https://www.google.com/");
4758  request.load_flags = 0;
4759
4760  // Attempt to fetch the URL from a server with a bad cert
4761  MockWrite bad_cert_writes[] = {
4762    MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4763              "Host: www.google.com\r\n"
4764              "Proxy-Connection: keep-alive\r\n\r\n"),
4765  };
4766
4767  MockRead bad_cert_reads[] = {
4768    MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
4769    MockRead(false, OK)
4770  };
4771
4772  // Attempt to fetch the URL with a good cert
4773  MockWrite good_data_writes[] = {
4774    MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4775              "Host: www.google.com\r\n"
4776              "Proxy-Connection: keep-alive\r\n\r\n"),
4777    MockWrite("GET / HTTP/1.1\r\n"
4778              "Host: www.google.com\r\n"
4779              "Connection: keep-alive\r\n\r\n"),
4780  };
4781
4782  MockRead good_cert_reads[] = {
4783    MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
4784    MockRead("HTTP/1.0 200 OK\r\n"),
4785    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4786    MockRead("Content-Length: 100\r\n\r\n"),
4787    MockRead(false, OK),
4788  };
4789
4790  StaticSocketDataProvider ssl_bad_certificate(
4791      bad_cert_reads, arraysize(bad_cert_reads),
4792      bad_cert_writes, arraysize(bad_cert_writes));
4793  StaticSocketDataProvider data(good_cert_reads, arraysize(good_cert_reads),
4794                                good_data_writes, arraysize(good_data_writes));
4795  SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
4796  SSLSocketDataProvider ssl(true, OK);
4797
4798  // SSL to the proxy, then CONNECT request, then SSL with bad certificate
4799  session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
4800  session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
4801  session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
4802
4803  // SSL to the proxy, then CONNECT request, then valid SSL certificate
4804  session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
4805  session_deps.socket_factory.AddSocketDataProvider(&data);
4806  session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
4807
4808  TestCompletionCallback callback;
4809
4810  scoped_ptr<HttpTransaction> trans(
4811      new HttpNetworkTransaction(CreateSession(&session_deps)));
4812
4813  int rv = trans->Start(&request, &callback, BoundNetLog());
4814  EXPECT_EQ(ERR_IO_PENDING, rv);
4815
4816  rv = callback.WaitForResult();
4817  EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
4818
4819  rv = trans->RestartIgnoringLastError(&callback);
4820  EXPECT_EQ(ERR_IO_PENDING, rv);
4821
4822  rv = callback.WaitForResult();
4823  EXPECT_EQ(OK, rv);
4824
4825  const HttpResponseInfo* response = trans->GetResponseInfo();
4826
4827  EXPECT_FALSE(response == NULL);
4828  EXPECT_EQ(100, response->headers->GetContentLength());
4829}
4830
4831TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
4832  HttpRequestInfo request;
4833  request.method = "GET";
4834  request.url = GURL("http://www.google.com/");
4835  request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
4836                                  "Chromium Ultra Awesome X Edition");
4837
4838  SessionDependencies session_deps;
4839  scoped_ptr<HttpTransaction> trans(
4840      new HttpNetworkTransaction(CreateSession(&session_deps)));
4841
4842  MockWrite data_writes[] = {
4843    MockWrite("GET / HTTP/1.1\r\n"
4844              "Host: www.google.com\r\n"
4845              "Connection: keep-alive\r\n"
4846              "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
4847  };
4848
4849  // Lastly, the server responds with the actual content.
4850  MockRead data_reads[] = {
4851    MockRead("HTTP/1.0 200 OK\r\n"),
4852    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4853    MockRead("Content-Length: 100\r\n\r\n"),
4854    MockRead(false, OK),
4855  };
4856
4857  StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4858                                data_writes, arraysize(data_writes));
4859  session_deps.socket_factory.AddSocketDataProvider(&data);
4860
4861  TestCompletionCallback callback;
4862
4863  int rv = trans->Start(&request, &callback, BoundNetLog());
4864  EXPECT_EQ(ERR_IO_PENDING, rv);
4865
4866  rv = callback.WaitForResult();
4867  EXPECT_EQ(OK, rv);
4868}
4869
4870TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgentOverTunnel) {
4871  HttpRequestInfo request;
4872  request.method = "GET";
4873  request.url = GURL("https://www.google.com/");
4874  request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
4875                                  "Chromium Ultra Awesome X Edition");
4876
4877  SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
4878  scoped_ptr<HttpTransaction> trans(
4879      new HttpNetworkTransaction(CreateSession(&session_deps)));
4880
4881  MockWrite data_writes[] = {
4882    MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4883              "Host: www.google.com\r\n"
4884              "Proxy-Connection: keep-alive\r\n"
4885              "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
4886  };
4887  MockRead data_reads[] = {
4888    // Return an error, so the transaction stops here (this test isn't
4889    // interested in the rest).
4890    MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4891    MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4892    MockRead("Proxy-Connection: close\r\n\r\n"),
4893  };
4894
4895  StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4896                                data_writes, arraysize(data_writes));
4897  session_deps.socket_factory.AddSocketDataProvider(&data);
4898
4899  TestCompletionCallback callback;
4900
4901  int rv = trans->Start(&request, &callback, BoundNetLog());
4902  EXPECT_EQ(ERR_IO_PENDING, rv);
4903
4904  rv = callback.WaitForResult();
4905  EXPECT_EQ(OK, rv);
4906}
4907
4908TEST_F(HttpNetworkTransactionTest, BuildRequest_Referer) {
4909  HttpRequestInfo request;
4910  request.method = "GET";
4911  request.url = GURL("http://www.google.com/");
4912  request.load_flags = 0;
4913  request.referrer = GURL("http://the.previous.site.com/");
4914
4915  SessionDependencies session_deps;
4916  scoped_ptr<HttpTransaction> trans(
4917      new HttpNetworkTransaction(CreateSession(&session_deps)));
4918
4919  MockWrite data_writes[] = {
4920    MockWrite("GET / HTTP/1.1\r\n"
4921              "Host: www.google.com\r\n"
4922              "Connection: keep-alive\r\n"
4923              "Referer: http://the.previous.site.com/\r\n\r\n"),
4924  };
4925
4926  // Lastly, the server responds with the actual content.
4927  MockRead data_reads[] = {
4928    MockRead("HTTP/1.0 200 OK\r\n"),
4929    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4930    MockRead("Content-Length: 100\r\n\r\n"),
4931    MockRead(false, OK),
4932  };
4933
4934  StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4935                                data_writes, arraysize(data_writes));
4936  session_deps.socket_factory.AddSocketDataProvider(&data);
4937
4938  TestCompletionCallback callback;
4939
4940  int rv = trans->Start(&request, &callback, BoundNetLog());
4941  EXPECT_EQ(ERR_IO_PENDING, rv);
4942
4943  rv = callback.WaitForResult();
4944  EXPECT_EQ(OK, rv);
4945}
4946
4947TEST_F(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
4948  HttpRequestInfo request;
4949  request.method = "POST";
4950  request.url = GURL("http://www.google.com/");
4951
4952  SessionDependencies session_deps;
4953  scoped_ptr<HttpTransaction> trans(
4954      new HttpNetworkTransaction(CreateSession(&session_deps)));
4955
4956  MockWrite data_writes[] = {
4957    MockWrite("POST / HTTP/1.1\r\n"
4958              "Host: www.google.com\r\n"
4959              "Connection: keep-alive\r\n"
4960              "Content-Length: 0\r\n\r\n"),
4961  };
4962
4963  // Lastly, the server responds with the actual content.
4964  MockRead data_reads[] = {
4965    MockRead("HTTP/1.0 200 OK\r\n"),
4966    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4967    MockRead("Content-Length: 100\r\n\r\n"),
4968    MockRead(false, OK),
4969  };
4970
4971  StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4972                                data_writes, arraysize(data_writes));
4973  session_deps.socket_factory.AddSocketDataProvider(&data);
4974
4975  TestCompletionCallback callback;
4976
4977  int rv = trans->Start(&request, &callback, BoundNetLog());
4978  EXPECT_EQ(ERR_IO_PENDING, rv);
4979
4980  rv = callback.WaitForResult();
4981  EXPECT_EQ(OK, rv);
4982}
4983
4984TEST_F(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
4985  HttpRequestInfo request;
4986  request.method = "PUT";
4987  request.url = GURL("http://www.google.com/");
4988
4989  SessionDependencies session_deps;
4990  scoped_ptr<HttpTransaction> trans(
4991      new HttpNetworkTransaction(CreateSession(&session_deps)));
4992
4993  MockWrite data_writes[] = {
4994    MockWrite("PUT / HTTP/1.1\r\n"
4995              "Host: www.google.com\r\n"
4996              "Connection: keep-alive\r\n"
4997              "Content-Length: 0\r\n\r\n"),
4998  };
4999
5000  // Lastly, the server responds with the actual content.
5001  MockRead data_reads[] = {
5002    MockRead("HTTP/1.0 200 OK\r\n"),
5003    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5004    MockRead("Content-Length: 100\r\n\r\n"),
5005    MockRead(false, OK),
5006  };
5007
5008  StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5009                                data_writes, arraysize(data_writes));
5010  session_deps.socket_factory.AddSocketDataProvider(&data);
5011
5012  TestCompletionCallback callback;
5013
5014  int rv = trans->Start(&request, &callback, BoundNetLog());
5015  EXPECT_EQ(ERR_IO_PENDING, rv);
5016
5017  rv = callback.WaitForResult();
5018  EXPECT_EQ(OK, rv);
5019}
5020
5021TEST_F(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
5022  HttpRequestInfo request;
5023  request.method = "HEAD";
5024  request.url = GURL("http://www.google.com/");
5025
5026  SessionDependencies session_deps;
5027  scoped_ptr<HttpTransaction> trans(
5028      new HttpNetworkTransaction(CreateSession(&session_deps)));
5029
5030  MockWrite data_writes[] = {
5031    MockWrite("HEAD / HTTP/1.1\r\n"
5032              "Host: www.google.com\r\n"
5033              "Connection: keep-alive\r\n"
5034              "Content-Length: 0\r\n\r\n"),
5035  };
5036
5037  // Lastly, the server responds with the actual content.
5038  MockRead data_reads[] = {
5039    MockRead("HTTP/1.0 200 OK\r\n"),
5040    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5041    MockRead("Content-Length: 100\r\n\r\n"),
5042    MockRead(false, OK),
5043  };
5044
5045  StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5046                                data_writes, arraysize(data_writes));
5047  session_deps.socket_factory.AddSocketDataProvider(&data);
5048
5049  TestCompletionCallback callback;
5050
5051  int rv = trans->Start(&request, &callback, BoundNetLog());
5052  EXPECT_EQ(ERR_IO_PENDING, rv);
5053
5054  rv = callback.WaitForResult();
5055  EXPECT_EQ(OK, rv);
5056}
5057
5058TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
5059  HttpRequestInfo request;
5060  request.method = "GET";
5061  request.url = GURL("http://www.google.com/");
5062  request.load_flags = LOAD_BYPASS_CACHE;
5063
5064  SessionDependencies session_deps;
5065  scoped_ptr<HttpTransaction> trans(
5066      new HttpNetworkTransaction(CreateSession(&session_deps)));
5067
5068  MockWrite data_writes[] = {
5069    MockWrite("GET / HTTP/1.1\r\n"
5070              "Host: www.google.com\r\n"
5071              "Connection: keep-alive\r\n"
5072              "Pragma: no-cache\r\n"
5073              "Cache-Control: no-cache\r\n\r\n"),
5074  };
5075
5076  // Lastly, the server responds with the actual content.
5077  MockRead data_reads[] = {
5078    MockRead("HTTP/1.0 200 OK\r\n"),
5079    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5080    MockRead("Content-Length: 100\r\n\r\n"),
5081    MockRead(false, OK),
5082  };
5083
5084  StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5085                                data_writes, arraysize(data_writes));
5086  session_deps.socket_factory.AddSocketDataProvider(&data);
5087
5088  TestCompletionCallback callback;
5089
5090  int rv = trans->Start(&request, &callback, BoundNetLog());
5091  EXPECT_EQ(ERR_IO_PENDING, rv);
5092
5093  rv = callback.WaitForResult();
5094  EXPECT_EQ(OK, rv);
5095}
5096
5097TEST_F(HttpNetworkTransactionTest,
5098       BuildRequest_CacheControlValidateCache) {
5099  HttpRequestInfo request;
5100  request.method = "GET";
5101  request.url = GURL("http://www.google.com/");
5102  request.load_flags = LOAD_VALIDATE_CACHE;
5103
5104  SessionDependencies session_deps;
5105  scoped_ptr<HttpTransaction> trans(
5106      new HttpNetworkTransaction(CreateSession(&session_deps)));
5107
5108  MockWrite data_writes[] = {
5109    MockWrite("GET / HTTP/1.1\r\n"
5110              "Host: www.google.com\r\n"
5111              "Connection: keep-alive\r\n"
5112              "Cache-Control: max-age=0\r\n\r\n"),
5113  };
5114
5115  // Lastly, the server responds with the actual content.
5116  MockRead data_reads[] = {
5117    MockRead("HTTP/1.0 200 OK\r\n"),
5118    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5119    MockRead("Content-Length: 100\r\n\r\n"),
5120    MockRead(false, OK),
5121  };
5122
5123  StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5124                                data_writes, arraysize(data_writes));
5125  session_deps.socket_factory.AddSocketDataProvider(&data);
5126
5127  TestCompletionCallback callback;
5128
5129  int rv = trans->Start(&request, &callback, BoundNetLog());
5130  EXPECT_EQ(ERR_IO_PENDING, rv);
5131
5132  rv = callback.WaitForResult();
5133  EXPECT_EQ(OK, rv);
5134}
5135
5136TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
5137  HttpRequestInfo request;
5138  request.method = "GET";
5139  request.url = GURL("http://www.google.com/");
5140  request.extra_headers.SetHeader("FooHeader", "Bar");
5141
5142  SessionDependencies session_deps;
5143  scoped_ptr<HttpTransaction> trans(
5144      new HttpNetworkTransaction(CreateSession(&session_deps)));
5145
5146  MockWrite data_writes[] = {
5147    MockWrite("GET / HTTP/1.1\r\n"
5148              "Host: www.google.com\r\n"
5149              "Connection: keep-alive\r\n"
5150              "FooHeader: Bar\r\n\r\n"),
5151  };
5152
5153  // Lastly, the server responds with the actual content.
5154  MockRead data_reads[] = {
5155    MockRead("HTTP/1.0 200 OK\r\n"),
5156    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5157    MockRead("Content-Length: 100\r\n\r\n"),
5158    MockRead(false, OK),
5159  };
5160
5161  StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5162                                data_writes, arraysize(data_writes));
5163  session_deps.socket_factory.AddSocketDataProvider(&data);
5164
5165  TestCompletionCallback callback;
5166
5167  int rv = trans->Start(&request, &callback, BoundNetLog());
5168  EXPECT_EQ(ERR_IO_PENDING, rv);
5169
5170  rv = callback.WaitForResult();
5171  EXPECT_EQ(OK, rv);
5172}
5173
5174TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) {
5175  HttpRequestInfo request;
5176  request.method = "GET";
5177  request.url = GURL("http://www.google.com/");
5178  request.extra_headers.SetHeader("referer", "www.foo.com");
5179  request.extra_headers.SetHeader("hEllo", "Kitty");
5180  request.extra_headers.SetHeader("FoO", "bar");
5181
5182  SessionDependencies session_deps;
5183  scoped_ptr<HttpTransaction> trans(
5184      new HttpNetworkTransaction(CreateSession(&session_deps)));
5185
5186  MockWrite data_writes[] = {
5187    MockWrite("GET / HTTP/1.1\r\n"
5188              "Host: www.google.com\r\n"
5189              "Connection: keep-alive\r\n"
5190              "hEllo: Kitty\r\n"
5191              "FoO: bar\r\n\r\n"),
5192  };
5193
5194  // Lastly, the server responds with the actual content.
5195  MockRead data_reads[] = {
5196    MockRead("HTTP/1.0 200 OK\r\n"),
5197    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5198    MockRead("Content-Length: 100\r\n\r\n"),
5199    MockRead(false, OK),
5200  };
5201
5202  StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5203                                data_writes, arraysize(data_writes));
5204  session_deps.socket_factory.AddSocketDataProvider(&data);
5205
5206  TestCompletionCallback callback;
5207
5208  int rv = trans->Start(&request, &callback, BoundNetLog());
5209  EXPECT_EQ(ERR_IO_PENDING, rv);
5210
5211  rv = callback.WaitForResult();
5212  EXPECT_EQ(OK, rv);
5213}
5214
5215TEST_F(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
5216  HttpRequestInfo request;
5217  request.method = "GET";
5218  request.url = GURL("http://www.google.com/");
5219  request.load_flags = 0;
5220
5221  SessionDependencies session_deps(
5222      ProxyService::CreateFixed("socks4://myproxy:1080"));
5223
5224  scoped_ptr<HttpTransaction> trans(
5225      new HttpNetworkTransaction(CreateSession(&session_deps)));
5226
5227  char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
5228  char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
5229
5230  MockWrite data_writes[] = {
5231    MockWrite(true, write_buffer, arraysize(write_buffer)),
5232    MockWrite("GET / HTTP/1.1\r\n"
5233              "Host: www.google.com\r\n"
5234              "Connection: keep-alive\r\n\r\n")
5235  };
5236
5237  MockRead data_reads[] = {
5238    MockRead(true, read_buffer, arraysize(read_buffer)),
5239    MockRead("HTTP/1.0 200 OK\r\n"),
5240    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
5241    MockRead("Payload"),
5242    MockRead(false, OK)
5243  };
5244
5245  StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5246                                data_writes, arraysize(data_writes));
5247  session_deps.socket_factory.AddSocketDataProvider(&data);
5248
5249  TestCompletionCallback callback;
5250
5251  int rv = trans->Start(&request, &callback, BoundNetLog());
5252  EXPECT_EQ(ERR_IO_PENDING, rv);
5253
5254  rv = callback.WaitForResult();
5255  EXPECT_EQ(OK, rv);
5256
5257  const HttpResponseInfo* response = trans->GetResponseInfo();
5258  EXPECT_FALSE(response == NULL);
5259
5260  std::string response_text;
5261  rv = ReadTransaction(trans.get(), &response_text);
5262  EXPECT_EQ(OK, rv);
5263  EXPECT_EQ("Payload", response_text);
5264}
5265
5266TEST_F(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
5267  HttpRequestInfo request;
5268  request.method = "GET";
5269  request.url = GURL("https://www.google.com/");
5270  request.load_flags = 0;
5271
5272  SessionDependencies session_deps(
5273      ProxyService::CreateFixed("socks4://myproxy:1080"));
5274
5275  scoped_ptr<HttpTransaction> trans(
5276      new HttpNetworkTransaction(CreateSession(&session_deps)));
5277
5278  unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
5279  unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
5280
5281  MockWrite data_writes[] = {
5282    MockWrite(true, reinterpret_cast<char*>(write_buffer),
5283              arraysize(write_buffer)),
5284    MockWrite("GET / HTTP/1.1\r\n"
5285              "Host: www.google.com\r\n"
5286              "Connection: keep-alive\r\n\r\n")
5287  };
5288
5289  MockRead data_reads[] = {
5290    MockWrite(true, reinterpret_cast<char*>(read_buffer),
5291              arraysize(read_buffer)),
5292    MockRead("HTTP/1.0 200 OK\r\n"),
5293    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
5294    MockRead("Payload"),
5295    MockRead(false, OK)
5296  };
5297
5298  StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5299                                data_writes, arraysize(data_writes));
5300  session_deps.socket_factory.AddSocketDataProvider(&data);
5301
5302  SSLSocketDataProvider ssl(true, OK);
5303  session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
5304
5305  TestCompletionCallback callback;
5306
5307  int rv = trans->Start(&request, &callback, BoundNetLog());
5308  EXPECT_EQ(ERR_IO_PENDING, rv);
5309
5310  rv = callback.WaitForResult();
5311  EXPECT_EQ(OK, rv);
5312
5313  const HttpResponseInfo* response = trans->GetResponseInfo();
5314  EXPECT_FALSE(response == NULL);
5315
5316  std::string response_text;
5317  rv = ReadTransaction(trans.get(), &response_text);
5318  EXPECT_EQ(OK, rv);
5319  EXPECT_EQ("Payload", response_text);
5320}
5321
5322TEST_F(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
5323  HttpRequestInfo request;
5324  request.method = "GET";
5325  request.url = GURL("http://www.google.com/");
5326  request.load_flags = 0;
5327
5328  SessionDependencies session_deps(
5329      ProxyService::CreateFixed("socks5://myproxy:1080"));
5330
5331  scoped_ptr<HttpTransaction> trans(
5332      new HttpNetworkTransaction(CreateSession(&session_deps)));
5333
5334  const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
5335  const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
5336  const char kSOCKS5OkRequest[] = {
5337    0x05,  // Version
5338    0x01,  // Command (CONNECT)
5339    0x00,  // Reserved.
5340    0x03,  // Address type (DOMAINNAME).
5341    0x0E,  // Length of domain (14)
5342    // Domain string:
5343    'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
5344    0x00, 0x50,  // 16-bit port (80)
5345  };
5346  const char kSOCKS5OkResponse[] =
5347      { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
5348
5349  MockWrite data_writes[] = {
5350    MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
5351    MockWrite(true, kSOCKS5OkRequest, arraysize(kSOCKS5OkRequest)),
5352    MockWrite("GET / HTTP/1.1\r\n"
5353              "Host: www.google.com\r\n"
5354              "Connection: keep-alive\r\n\r\n")
5355  };
5356
5357  MockRead data_reads[] = {
5358    MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
5359    MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
5360    MockRead("HTTP/1.0 200 OK\r\n"),
5361    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
5362    MockRead("Payload"),
5363    MockRead(false, OK)
5364  };
5365
5366  StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5367                                data_writes, arraysize(data_writes));
5368  session_deps.socket_factory.AddSocketDataProvider(&data);
5369
5370  TestCompletionCallback callback;
5371
5372  int rv = trans->Start(&request, &callback, BoundNetLog());
5373  EXPECT_EQ(ERR_IO_PENDING, rv);
5374
5375  rv = callback.WaitForResult();
5376  EXPECT_EQ(OK, rv);
5377
5378  const HttpResponseInfo* response = trans->GetResponseInfo();
5379  EXPECT_FALSE(response == NULL);
5380
5381  std::string response_text;
5382  rv = ReadTransaction(trans.get(), &response_text);
5383  EXPECT_EQ(OK, rv);
5384  EXPECT_EQ("Payload", response_text);
5385}
5386
5387TEST_F(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
5388  HttpRequestInfo request;
5389  request.method = "GET";
5390  request.url = GURL("https://www.google.com/");
5391  request.load_flags = 0;
5392
5393  SessionDependencies session_deps(
5394      ProxyService::CreateFixed("socks5://myproxy:1080"));
5395
5396  scoped_ptr<HttpTransaction> trans(
5397      new HttpNetworkTransaction(CreateSession(&session_deps)));
5398
5399  const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
5400  const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
5401  const unsigned char kSOCKS5OkRequest[] = {
5402    0x05,  // Version
5403    0x01,  // Command (CONNECT)
5404    0x00,  // Reserved.
5405    0x03,  // Address type (DOMAINNAME).
5406    0x0E,  // Length of domain (14)
5407    // Domain string:
5408    'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
5409    0x01, 0xBB,  // 16-bit port (443)
5410  };
5411
5412  const char kSOCKS5OkResponse[] =
5413      { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
5414
5415  MockWrite data_writes[] = {
5416    MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
5417    MockWrite(true, reinterpret_cast<const char*>(kSOCKS5OkRequest),
5418              arraysize(kSOCKS5OkRequest)),
5419    MockWrite("GET / HTTP/1.1\r\n"
5420              "Host: www.google.com\r\n"
5421              "Connection: keep-alive\r\n\r\n")
5422  };
5423
5424  MockRead data_reads[] = {
5425    MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
5426    MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
5427    MockRead("HTTP/1.0 200 OK\r\n"),
5428    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
5429    MockRead("Payload"),
5430    MockRead(false, OK)
5431  };
5432
5433  StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5434                                data_writes, arraysize(data_writes));
5435  session_deps.socket_factory.AddSocketDataProvider(&data);
5436
5437  SSLSocketDataProvider ssl(true, OK);
5438  session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
5439
5440  TestCompletionCallback callback;
5441
5442  int rv = trans->Start(&request, &callback, BoundNetLog());
5443  EXPECT_EQ(ERR_IO_PENDING, rv);
5444
5445  rv = callback.WaitForResult();
5446  EXPECT_EQ(OK, rv);
5447
5448  const HttpResponseInfo* response = trans->GetResponseInfo();
5449  EXPECT_FALSE(response == NULL);
5450
5451  std::string response_text;
5452  rv = ReadTransaction(trans.get(), &response_text);
5453  EXPECT_EQ(OK, rv);
5454  EXPECT_EQ("Payload", response_text);
5455}
5456
5457// Tests that for connection endpoints the group names are correctly set.
5458
5459struct GroupNameTest {
5460  std::string proxy_server;
5461  std::string url;
5462  std::string expected_group_name;
5463  bool ssl;
5464};
5465
5466scoped_refptr<HttpNetworkSession> SetupSessionForGroupNameTests(
5467    SessionDependencies* session_deps) {
5468  scoped_refptr<HttpNetworkSession> session(CreateSession(session_deps));
5469
5470  HttpAlternateProtocols* alternate_protocols =
5471      session->mutable_alternate_protocols();
5472  alternate_protocols->SetAlternateProtocolFor(
5473      HostPortPair("host.with.alternate", 80), 443,
5474      HttpAlternateProtocols::NPN_SPDY_2);
5475
5476  return session;
5477}
5478
5479int GroupNameTransactionHelper(
5480    const std::string& url,
5481    const scoped_refptr<HttpNetworkSession>& session) {
5482  HttpRequestInfo request;
5483  request.method = "GET";
5484  request.url = GURL(url);
5485  request.load_flags = 0;
5486
5487  scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5488
5489  TestCompletionCallback callback;
5490
5491  // We do not complete this request, the dtor will clean the transaction up.
5492  return trans->Start(&request, &callback, BoundNetLog());
5493}
5494
5495TEST_F(HttpNetworkTransactionTest, GroupNameForDirectConnections) {
5496  const GroupNameTest tests[] = {
5497    {
5498      "",  // unused
5499      "http://www.google.com/direct",
5500      "www.google.com:80",
5501      false,
5502    },
5503    {
5504      "",  // unused
5505      "http://[2001:1418:13:1::25]/direct",
5506      "[2001:1418:13:1::25]:80",
5507      false,
5508    },
5509
5510    // SSL Tests
5511    {
5512      "",  // unused
5513      "https://www.google.com/direct_ssl",
5514      "ssl/www.google.com:443",
5515      true,
5516    },
5517    {
5518      "",  // unused
5519      "https://[2001:1418:13:1::25]/direct",
5520      "ssl/[2001:1418:13:1::25]:443",
5521      true,
5522    },
5523    {
5524      "",  // unused
5525      "http://host.with.alternate/direct",
5526      "ssl/host.with.alternate:443",
5527      true,
5528    },
5529  };
5530
5531  HttpStreamFactory::set_use_alternate_protocols(true);
5532
5533  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
5534    SessionDependencies session_deps(
5535        ProxyService::CreateFixed(tests[i].proxy_server));
5536    scoped_refptr<HttpNetworkSession> session(
5537        SetupSessionForGroupNameTests(&session_deps));
5538
5539    HttpNetworkSessionPeer peer(session);
5540    CaptureGroupNameTransportSocketPool* transport_conn_pool =
5541        new CaptureGroupNameTransportSocketPool(NULL, NULL);
5542    peer.SetTransportSocketPool(transport_conn_pool);
5543    CaptureGroupNameSSLSocketPool* ssl_conn_pool =
5544        new CaptureGroupNameSSLSocketPool(NULL, NULL);
5545    peer.SetSSLSocketPool(ssl_conn_pool);
5546
5547    EXPECT_EQ(ERR_IO_PENDING,
5548              GroupNameTransactionHelper(tests[i].url, session));
5549    if (tests[i].ssl)
5550      EXPECT_EQ(tests[i].expected_group_name,
5551                ssl_conn_pool->last_group_name_received());
5552    else
5553      EXPECT_EQ(tests[i].expected_group_name,
5554                transport_conn_pool->last_group_name_received());
5555  }
5556
5557  HttpStreamFactory::set_use_alternate_protocols(false);
5558}
5559
5560TEST_F(HttpNetworkTransactionTest, GroupNameForHTTPProxyConnections) {
5561  const GroupNameTest tests[] = {
5562    {
5563      "http_proxy",
5564      "http://www.google.com/http_proxy_normal",
5565      "www.google.com:80",
5566      false,
5567    },
5568
5569    // SSL Tests
5570    {
5571      "http_proxy",
5572      "https://www.google.com/http_connect_ssl",
5573      "ssl/www.google.com:443",
5574      true,
5575    },
5576
5577    {
5578      "http_proxy",
5579      "http://host.with.alternate/direct",
5580      "ssl/host.with.alternate:443",
5581      true,
5582    },
5583  };
5584
5585  HttpStreamFactory::set_use_alternate_protocols(true);
5586
5587  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
5588    SessionDependencies session_deps(
5589        ProxyService::CreateFixed(tests[i].proxy_server));
5590    scoped_refptr<HttpNetworkSession> session(
5591        SetupSessionForGroupNameTests(&session_deps));
5592
5593    HttpNetworkSessionPeer peer(session);
5594
5595    HostPortPair proxy_host("http_proxy", 80);
5596    CaptureGroupNameHttpProxySocketPool* http_proxy_pool =
5597        new CaptureGroupNameHttpProxySocketPool(NULL, NULL);
5598    peer.SetSocketPoolForHTTPProxy(proxy_host, http_proxy_pool);
5599    CaptureGroupNameSSLSocketPool* ssl_conn_pool =
5600        new CaptureGroupNameSSLSocketPool(NULL, NULL);
5601    peer.SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
5602
5603    EXPECT_EQ(ERR_IO_PENDING,
5604              GroupNameTransactionHelper(tests[i].url, session));
5605    if (tests[i].ssl)
5606      EXPECT_EQ(tests[i].expected_group_name,
5607                ssl_conn_pool->last_group_name_received());
5608    else
5609      EXPECT_EQ(tests[i].expected_group_name,
5610                http_proxy_pool->last_group_name_received());
5611  }
5612
5613  HttpStreamFactory::set_use_alternate_protocols(false);
5614}
5615
5616TEST_F(HttpNetworkTransactionTest, GroupNameForSOCKSConnections) {
5617  const GroupNameTest tests[] = {
5618    {
5619      "socks4://socks_proxy:1080",
5620      "http://www.google.com/socks4_direct",
5621      "socks4/www.google.com:80",
5622      false,
5623    },
5624    {
5625      "socks5://socks_proxy:1080",
5626      "http://www.google.com/socks5_direct",
5627      "socks5/www.google.com:80",
5628      false,
5629    },
5630
5631    // SSL Tests
5632    {
5633      "socks4://socks_proxy:1080",
5634      "https://www.google.com/socks4_ssl",
5635      "socks4/ssl/www.google.com:443",
5636      true,
5637    },
5638    {
5639      "socks5://socks_proxy:1080",
5640      "https://www.google.com/socks5_ssl",
5641      "socks5/ssl/www.google.com:443",
5642      true,
5643    },
5644
5645    {
5646      "socks4://socks_proxy:1080",
5647      "http://host.with.alternate/direct",
5648      "socks4/ssl/host.with.alternate:443",
5649      true,
5650    },
5651  };
5652
5653  HttpStreamFactory::set_use_alternate_protocols(true);
5654
5655  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
5656    SessionDependencies session_deps(
5657        ProxyService::CreateFixed(tests[i].proxy_server));
5658    scoped_refptr<HttpNetworkSession> session(
5659        SetupSessionForGroupNameTests(&session_deps));
5660
5661    HttpNetworkSessionPeer peer(session);
5662
5663    HostPortPair proxy_host("socks_proxy", 1080);
5664    CaptureGroupNameSOCKSSocketPool* socks_conn_pool =
5665        new CaptureGroupNameSOCKSSocketPool(NULL, NULL);
5666    peer.SetSocketPoolForSOCKSProxy(proxy_host, socks_conn_pool);
5667    CaptureGroupNameSSLSocketPool* ssl_conn_pool =
5668        new CaptureGroupNameSSLSocketPool(NULL, NULL);
5669    peer.SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
5670
5671    scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5672
5673    EXPECT_EQ(ERR_IO_PENDING,
5674              GroupNameTransactionHelper(tests[i].url, session));
5675    if (tests[i].ssl)
5676      EXPECT_EQ(tests[i].expected_group_name,
5677                ssl_conn_pool->last_group_name_received());
5678    else
5679      EXPECT_EQ(tests[i].expected_group_name,
5680                socks_conn_pool->last_group_name_received());
5681  }
5682
5683  HttpStreamFactory::set_use_alternate_protocols(false);
5684}
5685
5686TEST_F(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
5687  HttpRequestInfo request;
5688  request.method = "GET";
5689  request.url = GURL("http://www.google.com/");
5690
5691  SessionDependencies session_deps(
5692      ProxyService::CreateFixed("myproxy:70;foobar:80"));
5693
5694  // This simulates failure resolving all hostnames; that means we will fail
5695  // connecting to both proxies (myproxy:70 and foobar:80).
5696  session_deps.host_resolver->rules()->AddSimulatedFailure("*");
5697
5698  scoped_ptr<HttpTransaction> trans(
5699      new HttpNetworkTransaction(CreateSession(&session_deps)));
5700
5701  TestCompletionCallback callback;
5702
5703  int rv = trans->Start(&request, &callback, BoundNetLog());
5704  EXPECT_EQ(ERR_IO_PENDING, rv);
5705
5706  rv = callback.WaitForResult();
5707  EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED, rv);
5708}
5709
5710// Host resolution observer used by
5711// HttpNetworkTransactionTest.ResolveMadeWithReferrer to check that host
5712// resovle requests are issued with a referrer of |expected_referrer|.
5713class ResolutionReferrerObserver : public HostResolver::Observer {
5714 public:
5715  explicit ResolutionReferrerObserver(const GURL& expected_referrer)
5716      : expected_referrer_(expected_referrer),
5717        called_start_with_referrer_(false),
5718        called_finish_with_referrer_(false) {
5719  }
5720
5721  virtual void OnStartResolution(int id,
5722                                 const HostResolver::RequestInfo& info) {
5723    if (info.referrer() == expected_referrer_)
5724      called_start_with_referrer_ = true;
5725  }
5726
5727  virtual void OnFinishResolutionWithStatus(
5728      int id, bool was_resolved, const HostResolver::RequestInfo& info ) {
5729    if (info.referrer() == expected_referrer_)
5730      called_finish_with_referrer_ = true;
5731  }
5732
5733  virtual void OnCancelResolution(int id,
5734                                  const HostResolver::RequestInfo& info ) {
5735    FAIL() << "Should not be cancelling any requests!";
5736  }
5737
5738  bool did_complete_with_expected_referrer() const {
5739    return called_start_with_referrer_ && called_finish_with_referrer_;
5740  }
5741
5742 private:
5743  GURL expected_referrer_;
5744  bool called_start_with_referrer_;
5745  bool called_finish_with_referrer_;
5746
5747  DISALLOW_COPY_AND_ASSIGN(ResolutionReferrerObserver);
5748};
5749
5750// Make sure that when HostResolver::Resolve() is invoked, it passes through
5751// the "referrer". This is depended on by the DNS prefetch observer.
5752TEST_F(HttpNetworkTransactionTest, ResolveMadeWithReferrer) {
5753  GURL referrer = GURL("http://expected-referrer/");
5754  EXPECT_TRUE(referrer.is_valid());
5755  ResolutionReferrerObserver resolution_observer(referrer);
5756
5757  // Issue a request, containing an HTTP referrer.
5758  HttpRequestInfo request;
5759  request.method = "GET";
5760  request.referrer = referrer;
5761  request.url = GURL("http://www.google.com/");
5762
5763  SessionDependencies session_deps;
5764  scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
5765      CreateSession(&session_deps)));
5766
5767  // Attach an observer to watch the host resolutions being made.
5768  session_deps.host_resolver->AddObserver(&resolution_observer);
5769
5770  // Connect up a mock socket which will fail when reading.
5771  MockRead data_reads[] = {
5772    MockRead(false, ERR_FAILED),
5773  };
5774  StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
5775  session_deps.socket_factory.AddSocketDataProvider(&data);
5776
5777  // Run the request until it fails reading from the socket.
5778  TestCompletionCallback callback;
5779  int rv = trans->Start(&request, &callback, BoundNetLog());
5780  EXPECT_EQ(ERR_IO_PENDING, rv);
5781  rv = callback.WaitForResult();
5782  EXPECT_EQ(ERR_FAILED, rv);
5783
5784  // Check that the host resolution observer saw |referrer|.
5785  EXPECT_TRUE(resolution_observer.did_complete_with_expected_referrer());
5786}
5787
5788// Base test to make sure that when the load flags for a request specify to
5789// bypass the cache, the DNS cache is not used.
5790void BypassHostCacheOnRefreshHelper(int load_flags) {
5791  // Issue a request, asking to bypass the cache(s).
5792  HttpRequestInfo request;
5793  request.method = "GET";
5794  request.load_flags = load_flags;
5795  request.url = GURL("http://www.google.com/");
5796
5797  SessionDependencies session_deps;
5798
5799  // Select a host resolver that does caching.
5800  session_deps.host_resolver.reset(new MockCachingHostResolver);
5801
5802  scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
5803      CreateSession(&session_deps)));
5804
5805  // Warm up the host cache so it has an entry for "www.google.com" (by doing
5806  // a synchronous lookup.)
5807  AddressList addrlist;
5808  int rv = session_deps.host_resolver->Resolve(
5809      HostResolver::RequestInfo(HostPortPair("www.google.com", 80)), &addrlist,
5810      NULL, NULL, BoundNetLog());
5811  EXPECT_EQ(OK, rv);
5812
5813  // Verify that it was added to host cache, by doing a subsequent async lookup
5814  // and confirming it completes synchronously.
5815  TestCompletionCallback resolve_callback;
5816  rv = session_deps.host_resolver->Resolve(
5817      HostResolver::RequestInfo(HostPortPair("www.google.com", 80)), &addrlist,
5818      &resolve_callback, NULL, BoundNetLog());
5819  ASSERT_EQ(OK, rv);
5820
5821  // Inject a failure the next time that "www.google.com" is resolved. This way
5822  // we can tell if the next lookup hit the cache, or the "network".
5823  // (cache --> success, "network" --> failure).
5824  session_deps.host_resolver->rules()->AddSimulatedFailure("www.google.com");
5825
5826  // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
5827  // first read -- this won't be reached as the host resolution will fail first.
5828  MockRead data_reads[] = { MockRead(false, ERR_UNEXPECTED) };
5829  StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
5830  session_deps.socket_factory.AddSocketDataProvider(&data);
5831
5832  // Run the request.
5833  TestCompletionCallback callback;
5834  rv = trans->Start(&request, &callback, BoundNetLog());
5835  ASSERT_EQ(ERR_IO_PENDING, rv);
5836  rv = callback.WaitForResult();
5837
5838  // If we bypassed the cache, we would have gotten a failure while resolving
5839  // "www.google.com".
5840  EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
5841}
5842
5843// There are multiple load flags that should trigger the host cache bypass.
5844// Test each in isolation:
5845TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh1) {
5846  BypassHostCacheOnRefreshHelper(LOAD_BYPASS_CACHE);
5847}
5848
5849TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh2) {
5850  BypassHostCacheOnRefreshHelper(LOAD_VALIDATE_CACHE);
5851}
5852
5853TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh3) {
5854  BypassHostCacheOnRefreshHelper(LOAD_DISABLE_CACHE);
5855}
5856
5857// Make sure we can handle an error when writing the request.
5858TEST_F(HttpNetworkTransactionTest, RequestWriteError) {
5859  SessionDependencies session_deps;
5860  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5861
5862  HttpRequestInfo request;
5863  request.method = "GET";
5864  request.url = GURL("http://www.foo.com/");
5865  request.load_flags = 0;
5866
5867  MockWrite write_failure[] = {
5868    MockWrite(true, ERR_CONNECTION_RESET),
5869  };
5870  StaticSocketDataProvider data(NULL, 0,
5871                                write_failure, arraysize(write_failure));
5872  session_deps.socket_factory.AddSocketDataProvider(&data);
5873
5874  TestCompletionCallback callback;
5875
5876  scoped_ptr<HttpTransaction> trans(
5877      new HttpNetworkTransaction(CreateSession(&session_deps)));
5878
5879  int rv = trans->Start(&request, &callback, BoundNetLog());
5880  EXPECT_EQ(ERR_IO_PENDING, rv);
5881
5882  rv = callback.WaitForResult();
5883  EXPECT_EQ(ERR_CONNECTION_RESET, rv);
5884}
5885
5886// Check that a connection closed after the start of the headers finishes ok.
5887TEST_F(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
5888  SessionDependencies session_deps;
5889  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5890
5891  HttpRequestInfo request;
5892  request.method = "GET";
5893  request.url = GURL("http://www.foo.com/");
5894  request.load_flags = 0;
5895
5896  MockRead data_reads[] = {
5897    MockRead("HTTP/1."),
5898    MockRead(false, OK),
5899  };
5900
5901  StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
5902  session_deps.socket_factory.AddSocketDataProvider(&data);
5903
5904  TestCompletionCallback callback;
5905
5906  scoped_ptr<HttpTransaction> trans(
5907      new HttpNetworkTransaction(CreateSession(&session_deps)));
5908
5909  int rv = trans->Start(&request, &callback, BoundNetLog());
5910  EXPECT_EQ(ERR_IO_PENDING, rv);
5911
5912  rv = callback.WaitForResult();
5913  EXPECT_EQ(OK, rv);
5914
5915  const HttpResponseInfo* response = trans->GetResponseInfo();
5916  EXPECT_TRUE(response != NULL);
5917
5918  EXPECT_TRUE(response->headers != NULL);
5919  EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
5920
5921  std::string response_data;
5922  rv = ReadTransaction(trans.get(), &response_data);
5923  EXPECT_EQ(OK, rv);
5924  EXPECT_EQ("", response_data);
5925}
5926
5927// Make sure that a dropped connection while draining the body for auth
5928// restart does the right thing.
5929TEST_F(HttpNetworkTransactionTest, DrainResetOK) {
5930  SessionDependencies session_deps;
5931  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5932
5933  HttpRequestInfo request;
5934  request.method = "GET";
5935  request.url = GURL("http://www.google.com/");
5936  request.load_flags = 0;
5937
5938  MockWrite data_writes1[] = {
5939    MockWrite("GET / HTTP/1.1\r\n"
5940              "Host: www.google.com\r\n"
5941              "Connection: keep-alive\r\n\r\n"),
5942  };
5943
5944  MockRead data_reads1[] = {
5945    MockRead("HTTP/1.1 401 Unauthorized\r\n"),
5946    MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5947    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5948    MockRead("Content-Length: 14\r\n\r\n"),
5949    MockRead("Unauth"),
5950    MockRead(true, ERR_CONNECTION_RESET),
5951  };
5952
5953  StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5954                                 data_writes1, arraysize(data_writes1));
5955  session_deps.socket_factory.AddSocketDataProvider(&data1);
5956
5957  // After calling trans->RestartWithAuth(), this is the request we should
5958  // be issuing -- the final header line contains the credentials.
5959  MockWrite data_writes2[] = {
5960    MockWrite("GET / HTTP/1.1\r\n"
5961              "Host: www.google.com\r\n"
5962              "Connection: keep-alive\r\n"
5963              "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5964  };
5965
5966  // Lastly, the server responds with the actual content.
5967  MockRead data_reads2[] = {
5968    MockRead("HTTP/1.1 200 OK\r\n"),
5969    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5970    MockRead("Content-Length: 100\r\n\r\n"),
5971    MockRead(false, OK),
5972  };
5973
5974  StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5975                                 data_writes2, arraysize(data_writes2));
5976  session_deps.socket_factory.AddSocketDataProvider(&data2);
5977
5978  TestCompletionCallback callback1;
5979
5980  scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5981
5982  int rv = trans->Start(&request, &callback1, BoundNetLog());
5983  EXPECT_EQ(ERR_IO_PENDING, rv);
5984
5985  rv = callback1.WaitForResult();
5986  EXPECT_EQ(OK, rv);
5987
5988  const HttpResponseInfo* response = trans->GetResponseInfo();
5989  EXPECT_FALSE(response == NULL);
5990
5991  // The password prompt info should have been set in response->auth_challenge.
5992  EXPECT_FALSE(response->auth_challenge.get() == NULL);
5993
5994  EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
5995  EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
5996  EXPECT_EQ(L"basic", response->auth_challenge->scheme);
5997
5998  TestCompletionCallback callback2;
5999
6000  rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
6001  EXPECT_EQ(ERR_IO_PENDING, rv);
6002
6003  rv = callback2.WaitForResult();
6004  EXPECT_EQ(OK, rv);
6005
6006  response = trans->GetResponseInfo();
6007  EXPECT_FALSE(response == NULL);
6008  EXPECT_TRUE(response->auth_challenge.get() == NULL);
6009  EXPECT_EQ(100, response->headers->GetContentLength());
6010}
6011
6012// Test HTTPS connections going through a proxy that sends extra data.
6013TEST_F(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
6014  SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
6015
6016  HttpRequestInfo request;
6017  request.method = "GET";
6018  request.url = GURL("https://www.google.com/");
6019  request.load_flags = 0;
6020
6021  MockRead proxy_reads[] = {
6022    MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
6023    MockRead(false, OK)
6024  };
6025
6026  StaticSocketDataProvider data(proxy_reads, arraysize(proxy_reads), NULL, 0);
6027  SSLSocketDataProvider ssl(true, OK);
6028
6029  session_deps.socket_factory.AddSocketDataProvider(&data);
6030  session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6031
6032  TestCompletionCallback callback;
6033
6034  session_deps.socket_factory.ResetNextMockIndexes();
6035
6036  scoped_ptr<HttpTransaction> trans(
6037      new HttpNetworkTransaction(CreateSession(&session_deps)));
6038
6039  int rv = trans->Start(&request, &callback, BoundNetLog());
6040  EXPECT_EQ(ERR_IO_PENDING, rv);
6041
6042  rv = callback.WaitForResult();
6043  EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
6044}
6045
6046TEST_F(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
6047  HttpRequestInfo request;
6048  request.method = "GET";
6049  request.url = GURL("http://www.google.com/");
6050  request.load_flags = 0;
6051
6052  SessionDependencies session_deps;
6053  scoped_ptr<HttpTransaction> trans(
6054      new HttpNetworkTransaction(CreateSession(&session_deps)));
6055
6056  MockRead data_reads[] = {
6057    MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
6058    MockRead(false, OK),
6059  };
6060
6061  StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
6062  session_deps.socket_factory.AddSocketDataProvider(&data);
6063
6064  TestCompletionCallback callback;
6065
6066  int rv = trans->Start(&request, &callback, BoundNetLog());
6067  EXPECT_EQ(ERR_IO_PENDING, rv);
6068
6069  EXPECT_EQ(OK, callback.WaitForResult());
6070
6071  const HttpResponseInfo* response = trans->GetResponseInfo();
6072  EXPECT_TRUE(response != NULL);
6073
6074  EXPECT_TRUE(response->headers != NULL);
6075  EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
6076
6077  std::string response_data;
6078  rv = ReadTransaction(trans.get(), &response_data);
6079  EXPECT_EQ(ERR_CONNECTION_CLOSED, rv);
6080}
6081
6082TEST_F(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
6083  HttpRequestInfo request;
6084  request.method = "POST";
6085  request.url = GURL("http://www.google.com/upload");
6086  request.upload_data = new UploadData;
6087  request.load_flags = 0;
6088
6089  SessionDependencies session_deps;
6090  scoped_ptr<HttpTransaction> trans(
6091      new HttpNetworkTransaction(CreateSession(&session_deps)));
6092
6093  FilePath temp_file_path;
6094  ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file_path));
6095  const uint64 kFakeSize = 100000;  // file is actually blank
6096
6097  std::vector<UploadData::Element> elements;
6098  UploadData::Element element;
6099  element.SetToFilePath(temp_file_path);
6100  element.SetContentLength(kFakeSize);
6101  elements.push_back(element);
6102  request.upload_data->SetElements(elements);
6103  EXPECT_EQ(kFakeSize, request.upload_data->GetContentLength());
6104
6105  MockRead data_reads[] = {
6106    MockRead("HTTP/1.0 200 OK\r\n\r\n"),
6107    MockRead("hello world"),
6108    MockRead(false, OK),
6109  };
6110  StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
6111  session_deps.socket_factory.AddSocketDataProvider(&data);
6112
6113  TestCompletionCallback callback;
6114
6115  int rv = trans->Start(&request, &callback, BoundNetLog());
6116  EXPECT_EQ(ERR_IO_PENDING, rv);
6117
6118  rv = callback.WaitForResult();
6119  EXPECT_EQ(OK, rv);
6120
6121  const HttpResponseInfo* response = trans->GetResponseInfo();
6122  EXPECT_TRUE(response != NULL);
6123
6124  EXPECT_TRUE(response->headers != NULL);
6125  EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
6126
6127  std::string response_data;
6128  rv = ReadTransaction(trans.get(), &response_data);
6129  EXPECT_EQ(OK, rv);
6130  EXPECT_EQ("hello world", response_data);
6131
6132  file_util::Delete(temp_file_path, false);
6133}
6134
6135TEST_F(HttpNetworkTransactionTest, UploadUnreadableFile) {
6136  HttpRequestInfo request;
6137  request.method = "POST";
6138  request.url = GURL("http://www.google.com/upload");
6139  request.upload_data = new UploadData;
6140  request.load_flags = 0;
6141
6142  // If we try to upload an unreadable file, the network stack should report
6143  // the file size as zero and upload zero bytes for that file.
6144  SessionDependencies session_deps;
6145  scoped_ptr<HttpTransaction> trans(
6146      new HttpNetworkTransaction(CreateSession(&session_deps)));
6147
6148  FilePath temp_file;
6149  ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
6150  std::string temp_file_content("Unreadable file.");
6151  ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_content.c_str(),
6152                                   temp_file_content.length()));
6153  ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
6154
6155  std::vector<UploadData::Element> elements;
6156  UploadData::Element element;
6157  element.SetToFilePath(temp_file);
6158  elements.push_back(element);
6159  request.upload_data->SetElements(elements);
6160
6161  MockRead data_reads[] = {
6162    MockRead("HTTP/1.0 200 OK\r\n\r\n"),
6163    MockRead(false, OK),
6164  };
6165  MockWrite data_writes[] = {
6166    MockWrite("POST /upload HTTP/1.1\r\n"
6167              "Host: www.google.com\r\n"
6168              "Connection: keep-alive\r\n"
6169              "Content-Length: 0\r\n\r\n"),
6170    MockWrite(false, OK),
6171  };
6172  StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
6173                                arraysize(data_writes));
6174  session_deps.socket_factory.AddSocketDataProvider(&data);
6175
6176  TestCompletionCallback callback;
6177
6178  int rv = trans->Start(&request, &callback, BoundNetLog());
6179  EXPECT_EQ(ERR_IO_PENDING, rv);
6180
6181  rv = callback.WaitForResult();
6182  EXPECT_EQ(OK, rv);
6183
6184  const HttpResponseInfo* response = trans->GetResponseInfo();
6185  EXPECT_TRUE(response != NULL);
6186  EXPECT_TRUE(response->headers != NULL);
6187  EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
6188
6189  file_util::Delete(temp_file, false);
6190}
6191
6192TEST_F(HttpNetworkTransactionTest, UnreadableUploadFileAfterAuthRestart) {
6193  HttpRequestInfo request;
6194  request.method = "POST";
6195  request.url = GURL("http://www.google.com/upload");
6196  request.upload_data = new UploadData;
6197  request.load_flags = 0;
6198
6199  SessionDependencies session_deps;
6200  scoped_ptr<HttpTransaction> trans(
6201      new HttpNetworkTransaction(CreateSession(&session_deps)));
6202
6203  FilePath temp_file;
6204  ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
6205  std::string temp_file_contents("Unreadable file.");
6206  std::string unreadable_contents(temp_file_contents.length(), '\0');
6207  ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_contents.c_str(),
6208                                   temp_file_contents.length()));
6209
6210  std::vector<UploadData::Element> elements;
6211  UploadData::Element element;
6212  element.SetToFilePath(temp_file);
6213  elements.push_back(element);
6214  request.upload_data->SetElements(elements);
6215
6216  MockRead data_reads[] = {
6217    MockRead("HTTP/1.1 401 Unauthorized\r\n"),
6218    MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6219    MockRead("Content-Length: 0\r\n\r\n"),  // No response body.
6220
6221    MockRead("HTTP/1.1 200 OK\r\n"),
6222    MockRead("Content-Length: 0\r\n\r\n"),
6223    MockRead(false, OK),
6224  };
6225  MockWrite data_writes[] = {
6226    MockWrite("POST /upload HTTP/1.1\r\n"
6227              "Host: www.google.com\r\n"
6228              "Connection: keep-alive\r\n"
6229              "Content-Length: 16\r\n\r\n"),
6230    MockWrite(false, temp_file_contents.c_str()),
6231
6232    MockWrite("POST /upload HTTP/1.1\r\n"
6233              "Host: www.google.com\r\n"
6234              "Connection: keep-alive\r\n"
6235              "Content-Length: 16\r\n"
6236              "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
6237    MockWrite(false, unreadable_contents.c_str(), temp_file_contents.length()),
6238    MockWrite(false, OK),
6239  };
6240  StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
6241                                arraysize(data_writes));
6242  session_deps.socket_factory.AddSocketDataProvider(&data);
6243
6244  TestCompletionCallback callback1;
6245
6246  int rv = trans->Start(&request, &callback1, BoundNetLog());
6247  EXPECT_EQ(ERR_IO_PENDING, rv);
6248
6249  rv = callback1.WaitForResult();
6250  EXPECT_EQ(OK, rv);
6251
6252  const HttpResponseInfo* response = trans->GetResponseInfo();
6253  EXPECT_TRUE(response != NULL);
6254  EXPECT_TRUE(response->headers != NULL);
6255  EXPECT_EQ("HTTP/1.1 401 Unauthorized", response->headers->GetStatusLine());
6256
6257  // The password prompt info should have been set in response->auth_challenge.
6258  EXPECT_TRUE(response->auth_challenge.get() != NULL);
6259  EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
6260  EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
6261  EXPECT_EQ(L"basic", response->auth_challenge->scheme);
6262
6263  // Now make the file unreadable and try again.
6264  ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
6265
6266  TestCompletionCallback callback2;
6267
6268  rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
6269  EXPECT_EQ(ERR_IO_PENDING, rv);
6270
6271  rv = callback2.WaitForResult();
6272  EXPECT_EQ(OK, rv);
6273
6274  response = trans->GetResponseInfo();
6275  EXPECT_TRUE(response != NULL);
6276  EXPECT_TRUE(response->headers != NULL);
6277  EXPECT_TRUE(response->auth_challenge.get() == NULL);
6278  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6279
6280  file_util::Delete(temp_file, false);
6281}
6282
6283// Tests that changes to Auth realms are treated like auth rejections.
6284TEST_F(HttpNetworkTransactionTest, ChangeAuthRealms) {
6285  SessionDependencies session_deps;
6286
6287  HttpRequestInfo request;
6288  request.method = "GET";
6289  request.url = GURL("http://www.google.com/");
6290  request.load_flags = 0;
6291
6292  // First transaction will request a resource and receive a Basic challenge
6293  // with realm="first_realm".
6294  MockWrite data_writes1[] = {
6295    MockWrite("GET / HTTP/1.1\r\n"
6296              "Host: www.google.com\r\n"
6297              "Connection: keep-alive\r\n"
6298              "\r\n"),
6299  };
6300  MockRead data_reads1[] = {
6301    MockRead("HTTP/1.1 401 Unauthorized\r\n"
6302             "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
6303             "\r\n"),
6304  };
6305
6306  // After calling trans->RestartWithAuth(), provide an Authentication header
6307  // for first_realm. The server will reject and provide a challenge with
6308  // second_realm.
6309  MockWrite data_writes2[] = {
6310    MockWrite("GET / HTTP/1.1\r\n"
6311              "Host: www.google.com\r\n"
6312              "Connection: keep-alive\r\n"
6313              "Authorization: Basic Zmlyc3Q6YmF6\r\n"
6314              "\r\n"),
6315  };
6316  MockRead data_reads2[] = {
6317    MockRead("HTTP/1.1 401 Unauthorized\r\n"
6318             "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
6319             "\r\n"),
6320  };
6321
6322  // This again fails, and goes back to first_realm. Make sure that the
6323  // entry is removed from cache.
6324  MockWrite data_writes3[] = {
6325    MockWrite("GET / HTTP/1.1\r\n"
6326              "Host: www.google.com\r\n"
6327              "Connection: keep-alive\r\n"
6328              "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
6329              "\r\n"),
6330  };
6331  MockRead data_reads3[] = {
6332    MockRead("HTTP/1.1 401 Unauthorized\r\n"
6333             "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
6334             "\r\n"),
6335  };
6336
6337  // Try one last time (with the correct password) and get the resource.
6338  MockWrite data_writes4[] = {
6339    MockWrite("GET / HTTP/1.1\r\n"
6340              "Host: www.google.com\r\n"
6341              "Connection: keep-alive\r\n"
6342              "Authorization: Basic Zmlyc3Q6YmFy\r\n"
6343              "\r\n"),
6344  };
6345  MockRead data_reads4[] = {
6346    MockRead("HTTP/1.1 200 OK\r\n"
6347             "Content-Type: text/html; charset=iso-8859-1\r\n"
6348             "Content-Length: 5\r\n"
6349             "\r\n"
6350             "hello"),
6351  };
6352
6353  StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6354                                 data_writes1, arraysize(data_writes1));
6355  StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
6356                                 data_writes2, arraysize(data_writes2));
6357  StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
6358                                 data_writes3, arraysize(data_writes3));
6359  StaticSocketDataProvider data4(data_reads4, arraysize(data_reads4),
6360                                 data_writes4, arraysize(data_writes4));
6361  session_deps.socket_factory.AddSocketDataProvider(&data1);
6362  session_deps.socket_factory.AddSocketDataProvider(&data2);
6363  session_deps.socket_factory.AddSocketDataProvider(&data3);
6364  session_deps.socket_factory.AddSocketDataProvider(&data4);
6365
6366  TestCompletionCallback callback1;
6367
6368  scoped_ptr<HttpTransaction> trans(
6369      new HttpNetworkTransaction(CreateSession(&session_deps)));
6370
6371  // Issue the first request with Authorize headers. There should be a
6372  // password prompt for first_realm waiting to be filled in after the
6373  // transaction completes.
6374  int rv = trans->Start(&request, &callback1, BoundNetLog());
6375  EXPECT_EQ(ERR_IO_PENDING, rv);
6376  rv = callback1.WaitForResult();
6377  EXPECT_EQ(OK, rv);
6378  const HttpResponseInfo* response = trans->GetResponseInfo();
6379  ASSERT_FALSE(response == NULL);
6380  ASSERT_FALSE(response->auth_challenge.get() == NULL);
6381  EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
6382  EXPECT_EQ(L"first_realm", response->auth_challenge->realm);
6383  EXPECT_EQ(L"basic", response->auth_challenge->scheme);
6384
6385  // Issue the second request with an incorrect password. There should be a
6386  // password prompt for second_realm waiting to be filled in after the
6387  // transaction completes.
6388  TestCompletionCallback callback2;
6389  rv = trans->RestartWithAuth(kFirst, kBaz, &callback2);
6390  EXPECT_EQ(ERR_IO_PENDING, rv);
6391  rv = callback2.WaitForResult();
6392  EXPECT_EQ(OK, rv);
6393  response = trans->GetResponseInfo();
6394  ASSERT_FALSE(response == NULL);
6395  ASSERT_FALSE(response->auth_challenge.get() == NULL);
6396  EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
6397  EXPECT_EQ(L"second_realm", response->auth_challenge->realm);
6398  EXPECT_EQ(L"basic", response->auth_challenge->scheme);
6399
6400  // Issue the third request with another incorrect password. There should be
6401  // a password prompt for first_realm waiting to be filled in. If the password
6402  // prompt is not present, it indicates that the HttpAuthCacheEntry for
6403  // first_realm was not correctly removed.
6404  TestCompletionCallback callback3;
6405  rv = trans->RestartWithAuth(kSecond, kFou, &callback3);
6406  EXPECT_EQ(ERR_IO_PENDING, rv);
6407  rv = callback3.WaitForResult();
6408  EXPECT_EQ(OK, rv);
6409  response = trans->GetResponseInfo();
6410  ASSERT_FALSE(response == NULL);
6411  ASSERT_FALSE(response->auth_challenge.get() == NULL);
6412  EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
6413  EXPECT_EQ(L"first_realm", response->auth_challenge->realm);
6414  EXPECT_EQ(L"basic", response->auth_challenge->scheme);
6415
6416  // Issue the fourth request with the correct password and username.
6417  TestCompletionCallback callback4;
6418  rv = trans->RestartWithAuth(kFirst, kBar, &callback4);
6419  EXPECT_EQ(ERR_IO_PENDING, rv);
6420  rv = callback4.WaitForResult();
6421  EXPECT_EQ(OK, rv);
6422  response = trans->GetResponseInfo();
6423  ASSERT_FALSE(response == NULL);
6424  EXPECT_TRUE(response->auth_challenge.get() == NULL);
6425}
6426
6427TEST_F(HttpNetworkTransactionTest, HonorAlternateProtocolHeader) {
6428  HttpStreamFactory::set_next_protos("needs_to_be_set_for_this_test");
6429  HttpStreamFactory::set_use_alternate_protocols(true);
6430
6431  SessionDependencies session_deps;
6432
6433  MockRead data_reads[] = {
6434    MockRead("HTTP/1.1 200 OK\r\n"),
6435    MockRead(kAlternateProtocolHttpHeader),
6436    MockRead("hello world"),
6437    MockRead(false, OK),
6438  };
6439
6440  HttpRequestInfo request;
6441  request.method = "GET";
6442  request.url = GURL("http://www.google.com/");
6443  request.load_flags = 0;
6444
6445  StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
6446
6447  session_deps.socket_factory.AddSocketDataProvider(&data);
6448
6449  TestCompletionCallback callback;
6450
6451  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6452  scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6453
6454  int rv = trans->Start(&request, &callback, BoundNetLog());
6455  EXPECT_EQ(ERR_IO_PENDING, rv);
6456
6457  HostPortPair http_host_port_pair("www.google.com", 80);
6458  const HttpAlternateProtocols& alternate_protocols =
6459      session->alternate_protocols();
6460  EXPECT_FALSE(
6461      alternate_protocols.HasAlternateProtocolFor(http_host_port_pair));
6462
6463  EXPECT_EQ(OK, callback.WaitForResult());
6464
6465  const HttpResponseInfo* response = trans->GetResponseInfo();
6466  ASSERT_TRUE(response != NULL);
6467  ASSERT_TRUE(response->headers != NULL);
6468  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6469  EXPECT_FALSE(response->was_fetched_via_spdy);
6470  EXPECT_FALSE(response->was_npn_negotiated);
6471
6472  std::string response_data;
6473  ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6474  EXPECT_EQ("hello world", response_data);
6475
6476  ASSERT_TRUE(alternate_protocols.HasAlternateProtocolFor(http_host_port_pair));
6477  const HttpAlternateProtocols::PortProtocolPair alternate =
6478      alternate_protocols.GetAlternateProtocolFor(http_host_port_pair);
6479  HttpAlternateProtocols::PortProtocolPair expected_alternate;
6480  expected_alternate.port = 443;
6481  expected_alternate.protocol = HttpAlternateProtocols::NPN_SPDY_2;
6482  EXPECT_TRUE(expected_alternate.Equals(alternate));
6483
6484  HttpStreamFactory::set_use_alternate_protocols(false);
6485  HttpStreamFactory::set_next_protos("");
6486}
6487
6488TEST_F(HttpNetworkTransactionTest, MarkBrokenAlternateProtocolAndFallback) {
6489  HttpStreamFactory::set_use_alternate_protocols(true);
6490  SessionDependencies session_deps;
6491
6492  HttpRequestInfo request;
6493  request.method = "GET";
6494  request.url = GURL("http://www.google.com/");
6495  request.load_flags = 0;
6496
6497  MockConnect mock_connect(true, ERR_CONNECTION_REFUSED);
6498  StaticSocketDataProvider first_data;
6499  first_data.set_connect_data(mock_connect);
6500  session_deps.socket_factory.AddSocketDataProvider(&first_data);
6501
6502  MockRead data_reads[] = {
6503    MockRead("HTTP/1.1 200 OK\r\n\r\n"),
6504    MockRead("hello world"),
6505    MockRead(true, OK),
6506  };
6507  StaticSocketDataProvider second_data(
6508      data_reads, arraysize(data_reads), NULL, 0);
6509  session_deps.socket_factory.AddSocketDataProvider(&second_data);
6510
6511  TestCompletionCallback callback;
6512
6513  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6514
6515  HostPortPair http_host_port_pair("www.google.com", 80);
6516  HttpAlternateProtocols* alternate_protocols =
6517      session->mutable_alternate_protocols();
6518  alternate_protocols->SetAlternateProtocolFor(
6519      http_host_port_pair, 1234 /* port is ignored by MockConnect anyway */,
6520      HttpAlternateProtocols::NPN_SPDY_2);
6521
6522  scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6523
6524  int rv = trans->Start(&request, &callback, BoundNetLog());
6525  EXPECT_EQ(ERR_IO_PENDING, rv);
6526  EXPECT_EQ(OK, callback.WaitForResult());
6527
6528  const HttpResponseInfo* response = trans->GetResponseInfo();
6529  ASSERT_TRUE(response != NULL);
6530  ASSERT_TRUE(response->headers != NULL);
6531  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6532
6533  std::string response_data;
6534  ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6535  EXPECT_EQ("hello world", response_data);
6536
6537  ASSERT_TRUE(
6538      alternate_protocols->HasAlternateProtocolFor(http_host_port_pair));
6539  const HttpAlternateProtocols::PortProtocolPair alternate =
6540      alternate_protocols->GetAlternateProtocolFor(http_host_port_pair);
6541  EXPECT_EQ(HttpAlternateProtocols::BROKEN, alternate.protocol);
6542  HttpStreamFactory::set_use_alternate_protocols(false);
6543}
6544
6545TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) {
6546  HttpStreamFactory::set_use_alternate_protocols(true);
6547  HttpStreamFactory::set_next_protos(kExpectedNPNString);
6548  SessionDependencies session_deps;
6549
6550  HttpRequestInfo request;
6551  request.method = "GET";
6552  request.url = GURL("http://www.google.com/");
6553  request.load_flags = 0;
6554
6555  MockRead data_reads[] = {
6556    MockRead("HTTP/1.1 200 OK\r\n"),
6557    MockRead(kAlternateProtocolHttpHeader),
6558    MockRead("hello world"),
6559    MockRead(true, OK),
6560  };
6561
6562  StaticSocketDataProvider first_transaction(
6563      data_reads, arraysize(data_reads), NULL, 0);
6564  session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
6565
6566  SSLSocketDataProvider ssl(true, OK);
6567  ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
6568  ssl.next_proto = "spdy/2";
6569  ssl.was_npn_negotiated = true;
6570  session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6571
6572  scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
6573  MockWrite spdy_writes[] = { CreateMockWrite(*req) };
6574
6575  scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
6576  scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
6577  MockRead spdy_reads[] = {
6578    CreateMockRead(*resp),
6579    CreateMockRead(*data),
6580    MockRead(true, 0, 0),
6581  };
6582
6583  scoped_refptr<DelayedSocketData> spdy_data(
6584      new DelayedSocketData(
6585          1,  // wait for one write to finish before reading.
6586          spdy_reads, arraysize(spdy_reads),
6587          spdy_writes, arraysize(spdy_writes)));
6588  session_deps.socket_factory.AddSocketDataProvider(spdy_data);
6589
6590  MockConnect never_finishing_connect(false, ERR_IO_PENDING);
6591  StaticSocketDataProvider hanging_non_alternate_protocol_socket(
6592      NULL, 0, NULL, 0);
6593  hanging_non_alternate_protocol_socket.set_connect_data(
6594      never_finishing_connect);
6595  session_deps.socket_factory.AddSocketDataProvider(
6596      &hanging_non_alternate_protocol_socket);
6597
6598  TestCompletionCallback callback;
6599
6600  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6601  scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
6602
6603  int rv = trans->Start(&request, &callback, BoundNetLog());
6604  EXPECT_EQ(ERR_IO_PENDING, rv);
6605  EXPECT_EQ(OK, callback.WaitForResult());
6606
6607  const HttpResponseInfo* response = trans->GetResponseInfo();
6608  ASSERT_TRUE(response != NULL);
6609  ASSERT_TRUE(response->headers != NULL);
6610  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6611
6612  std::string response_data;
6613  ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6614  EXPECT_EQ("hello world", response_data);
6615
6616  trans.reset(new HttpNetworkTransaction(session));
6617
6618  rv = trans->Start(&request, &callback, BoundNetLog());
6619  EXPECT_EQ(ERR_IO_PENDING, rv);
6620  EXPECT_EQ(OK, callback.WaitForResult());
6621
6622  response = trans->GetResponseInfo();
6623  ASSERT_TRUE(response != NULL);
6624  ASSERT_TRUE(response->headers != NULL);
6625  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6626  EXPECT_TRUE(response->was_fetched_via_spdy);
6627  EXPECT_TRUE(response->was_npn_negotiated);
6628
6629  ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6630  EXPECT_EQ("hello!", response_data);
6631
6632  HttpStreamFactory::set_next_protos("");
6633  HttpStreamFactory::set_use_alternate_protocols(false);
6634}
6635
6636TEST_F(HttpNetworkTransactionTest, AlternateProtocolWithSpdyLateBinding) {
6637  HttpStreamFactory::set_use_alternate_protocols(true);
6638  HttpStreamFactory::set_next_protos(kExpectedNPNString);
6639  SessionDependencies session_deps;
6640
6641  HttpRequestInfo request;
6642  request.method = "GET";
6643  request.url = GURL("http://www.google.com/");
6644  request.load_flags = 0;
6645
6646  MockRead data_reads[] = {
6647    MockRead("HTTP/1.1 200 OK\r\n"),
6648    MockRead(kAlternateProtocolHttpHeader),
6649    MockRead("hello world"),
6650    MockRead(true, OK),
6651  };
6652
6653  StaticSocketDataProvider first_transaction(
6654      data_reads, arraysize(data_reads), NULL, 0);
6655  // Socket 1 is the HTTP transaction with the Alternate-Protocol header.
6656  session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
6657
6658  MockConnect never_finishing_connect(false, ERR_IO_PENDING);
6659  StaticSocketDataProvider hanging_socket(
6660      NULL, 0, NULL, 0);
6661  hanging_socket.set_connect_data(never_finishing_connect);
6662  // Socket 2 and 3 are the hanging Alternate-Protocol and
6663  // non-Alternate-Protocol jobs from the 2nd transaction.
6664  session_deps.socket_factory.AddSocketDataProvider(&hanging_socket);
6665  session_deps.socket_factory.AddSocketDataProvider(&hanging_socket);
6666
6667  SSLSocketDataProvider ssl(true, OK);
6668  ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
6669  ssl.next_proto = "spdy/2";
6670  ssl.was_npn_negotiated = true;
6671  session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6672
6673  scoped_ptr<spdy::SpdyFrame> req1(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
6674  scoped_ptr<spdy::SpdyFrame> req2(ConstructSpdyGet(NULL, 0, false, 3, LOWEST));
6675  MockWrite spdy_writes[] = {
6676    CreateMockWrite(*req1),
6677    CreateMockWrite(*req2),
6678  };
6679  scoped_ptr<spdy::SpdyFrame> resp1(ConstructSpdyGetSynReply(NULL, 0, 1));
6680  scoped_ptr<spdy::SpdyFrame> data1(ConstructSpdyBodyFrame(1, true));
6681  scoped_ptr<spdy::SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 3));
6682  scoped_ptr<spdy::SpdyFrame> data2(ConstructSpdyBodyFrame(3, true));
6683  MockRead spdy_reads[] = {
6684    CreateMockRead(*resp1),
6685    CreateMockRead(*data1),
6686    CreateMockRead(*resp2),
6687    CreateMockRead(*data2),
6688    MockRead(true, 0, 0),
6689  };
6690
6691  scoped_refptr<DelayedSocketData> spdy_data(
6692      new DelayedSocketData(
6693          2,  // wait for writes to finish before reading.
6694          spdy_reads, arraysize(spdy_reads),
6695          spdy_writes, arraysize(spdy_writes)));
6696  // Socket 4 is the successful Alternate-Protocol for transaction 3.
6697  session_deps.socket_factory.AddSocketDataProvider(spdy_data);
6698
6699  // Socket 5 is the unsuccessful non-Alternate-Protocol for transaction 3.
6700  session_deps.socket_factory.AddSocketDataProvider(&hanging_socket);
6701
6702  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6703  TestCompletionCallback callback1;
6704  HttpNetworkTransaction trans1(session);
6705
6706  int rv = trans1.Start(&request, &callback1, BoundNetLog());
6707  EXPECT_EQ(ERR_IO_PENDING, rv);
6708  EXPECT_EQ(OK, callback1.WaitForResult());
6709
6710  const HttpResponseInfo* response = trans1.GetResponseInfo();
6711  ASSERT_TRUE(response != NULL);
6712  ASSERT_TRUE(response->headers != NULL);
6713  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6714
6715  std::string response_data;
6716  ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
6717  EXPECT_EQ("hello world", response_data);
6718
6719  TestCompletionCallback callback2;
6720  HttpNetworkTransaction trans2(session);
6721  rv = trans2.Start(&request, &callback2, BoundNetLog());
6722  EXPECT_EQ(ERR_IO_PENDING, rv);
6723
6724  TestCompletionCallback callback3;
6725  HttpNetworkTransaction trans3(session);
6726  rv = trans3.Start(&request, &callback3, BoundNetLog());
6727  EXPECT_EQ(ERR_IO_PENDING, rv);
6728
6729  EXPECT_EQ(OK, callback2.WaitForResult());
6730  EXPECT_EQ(OK, callback3.WaitForResult());
6731
6732  response = trans2.GetResponseInfo();
6733  ASSERT_TRUE(response != NULL);
6734  ASSERT_TRUE(response->headers != NULL);
6735  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6736  EXPECT_TRUE(response->was_fetched_via_spdy);
6737  EXPECT_TRUE(response->was_npn_negotiated);
6738  ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
6739  EXPECT_EQ("hello!", response_data);
6740
6741  response = trans3.GetResponseInfo();
6742  ASSERT_TRUE(response != NULL);
6743  ASSERT_TRUE(response->headers != NULL);
6744  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6745  EXPECT_TRUE(response->was_fetched_via_spdy);
6746  EXPECT_TRUE(response->was_npn_negotiated);
6747  ASSERT_EQ(OK, ReadTransaction(&trans3, &response_data));
6748  EXPECT_EQ("hello!", response_data);
6749
6750  HttpStreamFactory::set_next_protos("");
6751  HttpStreamFactory::set_use_alternate_protocols(false);
6752}
6753
6754TEST_F(HttpNetworkTransactionTest, StallAlternateProtocolForNpnSpdy) {
6755  HttpStreamFactory::set_use_alternate_protocols(true);
6756  HttpStreamFactory::set_next_protos(kExpectedNPNString);
6757  SessionDependencies session_deps;
6758
6759  HttpRequestInfo request;
6760  request.method = "GET";
6761  request.url = GURL("http://www.google.com/");
6762  request.load_flags = 0;
6763
6764  MockRead data_reads[] = {
6765    MockRead("HTTP/1.1 200 OK\r\n"),
6766    MockRead(kAlternateProtocolHttpHeader),
6767    MockRead("hello world"),
6768    MockRead(true, OK),
6769  };
6770
6771  StaticSocketDataProvider first_transaction(
6772      data_reads, arraysize(data_reads), NULL, 0);
6773  session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
6774
6775  SSLSocketDataProvider ssl(true, OK);
6776  ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
6777  ssl.next_proto = "spdy/2";
6778  ssl.was_npn_negotiated = true;
6779  session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6780
6781  MockConnect never_finishing_connect(false, ERR_IO_PENDING);
6782  StaticSocketDataProvider hanging_alternate_protocol_socket(
6783      NULL, 0, NULL, 0);
6784  hanging_alternate_protocol_socket.set_connect_data(
6785      never_finishing_connect);
6786  session_deps.socket_factory.AddSocketDataProvider(
6787      &hanging_alternate_protocol_socket);
6788
6789  // 2nd request is just a copy of the first one, over HTTP again.
6790  session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
6791
6792  TestCompletionCallback callback;
6793
6794  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6795  scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
6796
6797  int rv = trans->Start(&request, &callback, BoundNetLog());
6798  EXPECT_EQ(ERR_IO_PENDING, rv);
6799  EXPECT_EQ(OK, callback.WaitForResult());
6800
6801  const HttpResponseInfo* response = trans->GetResponseInfo();
6802  ASSERT_TRUE(response != NULL);
6803  ASSERT_TRUE(response->headers != NULL);
6804  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6805
6806  std::string response_data;
6807  ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6808  EXPECT_EQ("hello world", response_data);
6809
6810  trans.reset(new HttpNetworkTransaction(session));
6811
6812  rv = trans->Start(&request, &callback, BoundNetLog());
6813  EXPECT_EQ(ERR_IO_PENDING, rv);
6814  EXPECT_EQ(OK, callback.WaitForResult());
6815
6816  response = trans->GetResponseInfo();
6817  ASSERT_TRUE(response != NULL);
6818  ASSERT_TRUE(response->headers != NULL);
6819  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6820  EXPECT_FALSE(response->was_fetched_via_spdy);
6821  EXPECT_FALSE(response->was_npn_negotiated);
6822
6823  ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6824  EXPECT_EQ("hello world", response_data);
6825
6826  HttpStreamFactory::set_next_protos("");
6827  HttpStreamFactory::set_use_alternate_protocols(false);
6828}
6829
6830class CapturingProxyResolver : public ProxyResolver {
6831 public:
6832  CapturingProxyResolver() : ProxyResolver(false /* expects_pac_bytes */) {}
6833  virtual ~CapturingProxyResolver() {}
6834
6835  virtual int GetProxyForURL(const GURL& url,
6836                             ProxyInfo* results,
6837                             CompletionCallback* callback,
6838                             RequestHandle* request,
6839                             const BoundNetLog& net_log) {
6840    ProxyServer proxy_server(ProxyServer::SCHEME_HTTP,
6841                             HostPortPair("myproxy", 80));
6842    results->UseProxyServer(proxy_server);
6843    resolved_.push_back(url);
6844    return OK;
6845  }
6846
6847  virtual void CancelRequest(RequestHandle request) {
6848    NOTREACHED();
6849  }
6850
6851  virtual void CancelSetPacScript() {
6852    NOTREACHED();
6853  }
6854
6855  virtual int SetPacScript(const scoped_refptr<ProxyResolverScriptData>&,
6856                           CompletionCallback* /*callback*/) {
6857    return OK;
6858  }
6859
6860  const std::vector<GURL>& resolved() const { return resolved_; }
6861
6862 private:
6863  std::vector<GURL> resolved_;
6864
6865  DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver);
6866};
6867
6868TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForTunneledNpnSpdy) {
6869  HttpStreamFactory::set_use_alternate_protocols(true);
6870  HttpStreamFactory::set_next_protos(kExpectedNPNString);
6871
6872  ProxyConfig proxy_config;
6873  proxy_config.set_auto_detect(true);
6874  proxy_config.set_pac_url(GURL("http://fooproxyurl"));
6875
6876  CapturingProxyResolver* capturing_proxy_resolver =
6877      new CapturingProxyResolver();
6878  SessionDependencies session_deps(new ProxyService(
6879      new ProxyConfigServiceFixed(proxy_config), capturing_proxy_resolver,
6880      NULL));
6881
6882  HttpRequestInfo request;
6883  request.method = "GET";
6884  request.url = GURL("http://www.google.com/");
6885  request.load_flags = 0;
6886
6887  MockRead data_reads[] = {
6888    MockRead("HTTP/1.1 200 OK\r\n"),
6889    MockRead(kAlternateProtocolHttpHeader),
6890    MockRead("hello world"),
6891    MockRead(true, OK),
6892  };
6893
6894  StaticSocketDataProvider first_transaction(
6895      data_reads, arraysize(data_reads), NULL, 0);
6896  session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
6897
6898  SSLSocketDataProvider ssl(true, OK);
6899  ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
6900  ssl.next_proto = "spdy/2";
6901  ssl.was_npn_negotiated = true;
6902  session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6903
6904  scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
6905  MockWrite spdy_writes[] = {
6906    MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6907              "Host: www.google.com\r\n"
6908              "Proxy-Connection: keep-alive\r\n\r\n"),  // 0
6909    CreateMockWrite(*req)  // 3
6910  };
6911
6912  const char kCONNECTResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
6913
6914  scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
6915  scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
6916  MockRead spdy_reads[] = {
6917    MockRead(true, kCONNECTResponse, arraysize(kCONNECTResponse) - 1, 1),  // 1
6918    CreateMockRead(*resp.get(), 4),  // 2, 4
6919    CreateMockRead(*data.get(), 4),  // 5
6920    MockRead(true, 0, 0, 4),  // 6
6921  };
6922
6923  scoped_refptr<OrderedSocketData> spdy_data(
6924      new OrderedSocketData(
6925          spdy_reads, arraysize(spdy_reads),
6926          spdy_writes, arraysize(spdy_writes)));
6927  session_deps.socket_factory.AddSocketDataProvider(spdy_data);
6928
6929  MockConnect never_finishing_connect(false, ERR_IO_PENDING);
6930  StaticSocketDataProvider hanging_non_alternate_protocol_socket(
6931      NULL, 0, NULL, 0);
6932  hanging_non_alternate_protocol_socket.set_connect_data(
6933      never_finishing_connect);
6934  session_deps.socket_factory.AddSocketDataProvider(
6935      &hanging_non_alternate_protocol_socket);
6936
6937  TestCompletionCallback callback;
6938
6939  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6940  scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
6941
6942  int rv = trans->Start(&request, &callback, BoundNetLog());
6943  EXPECT_EQ(ERR_IO_PENDING, rv);
6944  EXPECT_EQ(OK, callback.WaitForResult());
6945
6946  const HttpResponseInfo* response = trans->GetResponseInfo();
6947  ASSERT_TRUE(response != NULL);
6948  ASSERT_TRUE(response->headers != NULL);
6949  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6950  EXPECT_FALSE(response->was_fetched_via_spdy);
6951  EXPECT_FALSE(response->was_npn_negotiated);
6952
6953  std::string response_data;
6954  ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6955  EXPECT_EQ("hello world", response_data);
6956
6957  trans.reset(new HttpNetworkTransaction(session));
6958
6959  rv = trans->Start(&request, &callback, BoundNetLog());
6960  EXPECT_EQ(ERR_IO_PENDING, rv);
6961  EXPECT_EQ(OK, callback.WaitForResult());
6962
6963  response = trans->GetResponseInfo();
6964  ASSERT_TRUE(response != NULL);
6965  ASSERT_TRUE(response->headers != NULL);
6966  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6967  EXPECT_TRUE(response->was_fetched_via_spdy);
6968  EXPECT_TRUE(response->was_npn_negotiated);
6969
6970  ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6971  EXPECT_EQ("hello!", response_data);
6972  ASSERT_EQ(3u, capturing_proxy_resolver->resolved().size());
6973  EXPECT_EQ("http://www.google.com/",
6974            capturing_proxy_resolver->resolved()[0].spec());
6975  EXPECT_EQ("https://www.google.com/",
6976            capturing_proxy_resolver->resolved()[1].spec());
6977
6978  HttpStreamFactory::set_next_protos("");
6979  HttpStreamFactory::set_use_alternate_protocols(false);
6980}
6981
6982TEST_F(HttpNetworkTransactionTest,
6983       UseAlternateProtocolForNpnSpdyWithExistingSpdySession) {
6984  HttpStreamFactory::set_use_alternate_protocols(true);
6985  HttpStreamFactory::set_next_protos(kExpectedNPNString);
6986  SessionDependencies session_deps;
6987
6988  HttpRequestInfo request;
6989  request.method = "GET";
6990  request.url = GURL("http://www.google.com/");
6991  request.load_flags = 0;
6992
6993  MockRead data_reads[] = {
6994    MockRead("HTTP/1.1 200 OK\r\n"),
6995    MockRead(kAlternateProtocolHttpHeader),
6996    MockRead("hello world"),
6997    MockRead(true, OK),
6998  };
6999
7000  StaticSocketDataProvider first_transaction(
7001      data_reads, arraysize(data_reads), NULL, 0);
7002  session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
7003
7004  SSLSocketDataProvider ssl(true, OK);
7005  ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
7006  ssl.next_proto = "spdy/2";
7007  ssl.was_npn_negotiated = true;
7008  session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
7009  // Make sure we use ssl for spdy here.
7010  SpdySession::SetSSLMode(true);
7011
7012  scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
7013  MockWrite spdy_writes[] = { CreateMockWrite(*req) };
7014
7015  scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
7016  scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
7017  MockRead spdy_reads[] = {
7018    CreateMockRead(*resp),
7019    CreateMockRead(*data),
7020    MockRead(true, 0, 0),
7021  };
7022
7023  scoped_refptr<DelayedSocketData> spdy_data(
7024      new DelayedSocketData(
7025          1,  // wait for one write to finish before reading.
7026          spdy_reads, arraysize(spdy_reads),
7027          spdy_writes, arraysize(spdy_writes)));
7028  session_deps.socket_factory.AddSocketDataProvider(spdy_data);
7029
7030  TestCompletionCallback callback;
7031
7032  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7033
7034  scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
7035
7036  int rv = trans->Start(&request, &callback, BoundNetLog());
7037  EXPECT_EQ(ERR_IO_PENDING, rv);
7038  EXPECT_EQ(OK, callback.WaitForResult());
7039
7040  const HttpResponseInfo* response = trans->GetResponseInfo();
7041  ASSERT_TRUE(response != NULL);
7042  ASSERT_TRUE(response->headers != NULL);
7043  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7044
7045  std::string response_data;
7046  ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7047  EXPECT_EQ("hello world", response_data);
7048
7049  // Set up an initial SpdySession in the pool to reuse.
7050  HostPortPair host_port_pair("www.google.com", 443);
7051  HostPortProxyPair pair(host_port_pair, ProxyServer::Direct());
7052  scoped_refptr<SpdySession> spdy_session =
7053      session->spdy_session_pool()->Get(pair, BoundNetLog());
7054  scoped_refptr<TransportSocketParams> transport_params(
7055      new TransportSocketParams(host_port_pair, MEDIUM, GURL(), false, false));
7056
7057  scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle);
7058  EXPECT_EQ(ERR_IO_PENDING,
7059            connection->Init(host_port_pair.ToString(),
7060                             transport_params,
7061                             LOWEST,
7062                             &callback,
7063                             session->transport_socket_pool(),
7064                             BoundNetLog()));
7065  EXPECT_EQ(OK, callback.WaitForResult());
7066
7067  SSLConfig ssl_config;
7068  session->ssl_config_service()->GetSSLConfig(&ssl_config);
7069  scoped_ptr<ClientSocketHandle> ssl_connection(new ClientSocketHandle);
7070  ssl_connection->set_socket(session_deps.socket_factory.CreateSSLClientSocket(
7071      connection.release(), HostPortPair("" , 443), ssl_config,
7072      NULL /* ssl_host_info */, session_deps.cert_verifier.get(), NULL));
7073  EXPECT_EQ(ERR_IO_PENDING, ssl_connection->socket()->Connect(&callback));
7074  EXPECT_EQ(OK, callback.WaitForResult());
7075
7076  EXPECT_EQ(OK, spdy_session->InitializeWithSocket(ssl_connection.release(),
7077                                                   true, OK));
7078
7079  trans.reset(new HttpNetworkTransaction(session));
7080
7081  rv = trans->Start(&request, &callback, BoundNetLog());
7082  EXPECT_EQ(ERR_IO_PENDING, rv);
7083  EXPECT_EQ(OK, callback.WaitForResult());
7084
7085  response = trans->GetResponseInfo();
7086  ASSERT_TRUE(response != NULL);
7087  ASSERT_TRUE(response->headers != NULL);
7088  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7089  EXPECT_TRUE(response->was_fetched_via_spdy);
7090  EXPECT_TRUE(response->was_npn_negotiated);
7091
7092  ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7093  EXPECT_EQ("hello!", response_data);
7094
7095  HttpStreamFactory::set_next_protos("");
7096  HttpStreamFactory::set_use_alternate_protocols(false);
7097}
7098
7099// GenerateAuthToken is a mighty big test.
7100// It tests all permutation of GenerateAuthToken behavior:
7101//   - Synchronous and Asynchronous completion.
7102//   - OK or error on completion.
7103//   - Direct connection, non-authenticating proxy, and authenticating proxy.
7104//   - HTTP or HTTPS backend (to include proxy tunneling).
7105//   - Non-authenticating and authenticating backend.
7106//
7107// In all, there are 44 reasonable permuations (for example, if there are
7108// problems generating an auth token for an authenticating proxy, we don't
7109// need to test all permutations of the backend server).
7110//
7111// The test proceeds by going over each of the configuration cases, and
7112// potentially running up to three rounds in each of the tests. The TestConfig
7113// specifies both the configuration for the test as well as the expectations
7114// for the results.
7115TEST_F(HttpNetworkTransactionTest, GenerateAuthToken) {
7116  static const char kServer[] = "http://www.example.com";
7117  static const char kSecureServer[] = "https://www.example.com";
7118  static const char kProxy[] = "myproxy:70";
7119  const int kAuthErr = ERR_INVALID_AUTH_CREDENTIALS;
7120
7121  enum AuthTiming {
7122    AUTH_NONE,
7123    AUTH_SYNC,
7124    AUTH_ASYNC,
7125  };
7126
7127  const MockWrite kGet(
7128      "GET / HTTP/1.1\r\n"
7129      "Host: www.example.com\r\n"
7130      "Connection: keep-alive\r\n\r\n");
7131  const MockWrite kGetProxy(
7132      "GET http://www.example.com/ HTTP/1.1\r\n"
7133      "Host: www.example.com\r\n"
7134      "Proxy-Connection: keep-alive\r\n\r\n");
7135  const MockWrite kGetAuth(
7136      "GET / HTTP/1.1\r\n"
7137      "Host: www.example.com\r\n"
7138      "Connection: keep-alive\r\n"
7139      "Authorization: auth_token\r\n\r\n");
7140  const MockWrite kGetProxyAuth(
7141      "GET http://www.example.com/ HTTP/1.1\r\n"
7142      "Host: www.example.com\r\n"
7143      "Proxy-Connection: keep-alive\r\n"
7144      "Proxy-Authorization: auth_token\r\n\r\n");
7145  const MockWrite kGetAuthThroughProxy(
7146      "GET http://www.example.com/ HTTP/1.1\r\n"
7147      "Host: www.example.com\r\n"
7148      "Proxy-Connection: keep-alive\r\n"
7149      "Authorization: auth_token\r\n\r\n");
7150  const MockWrite kGetAuthWithProxyAuth(
7151      "GET http://www.example.com/ HTTP/1.1\r\n"
7152      "Host: www.example.com\r\n"
7153      "Proxy-Connection: keep-alive\r\n"
7154      "Proxy-Authorization: auth_token\r\n"
7155      "Authorization: auth_token\r\n\r\n");
7156  const MockWrite kConnect(
7157      "CONNECT www.example.com:443 HTTP/1.1\r\n"
7158      "Host: www.example.com\r\n"
7159      "Proxy-Connection: keep-alive\r\n\r\n");
7160  const MockWrite kConnectProxyAuth(
7161      "CONNECT www.example.com:443 HTTP/1.1\r\n"
7162      "Host: www.example.com\r\n"
7163      "Proxy-Connection: keep-alive\r\n"
7164      "Proxy-Authorization: auth_token\r\n\r\n");
7165
7166  const MockRead kSuccess(
7167      "HTTP/1.1 200 OK\r\n"
7168      "Content-Type: text/html; charset=iso-8859-1\r\n"
7169      "Content-Length: 3\r\n\r\n"
7170      "Yes");
7171  const MockRead kFailure(
7172      "Should not be called.");
7173  const MockRead kServerChallenge(
7174      "HTTP/1.1 401 Unauthorized\r\n"
7175      "WWW-Authenticate: Mock realm=server\r\n"
7176      "Content-Type: text/html; charset=iso-8859-1\r\n"
7177      "Content-Length: 14\r\n\r\n"
7178      "Unauthorized\r\n");
7179  const MockRead kProxyChallenge(
7180      "HTTP/1.1 407 Unauthorized\r\n"
7181      "Proxy-Authenticate: Mock realm=proxy\r\n"
7182      "Proxy-Connection: close\r\n"
7183      "Content-Type: text/html; charset=iso-8859-1\r\n"
7184      "Content-Length: 14\r\n\r\n"
7185      "Unauthorized\r\n");
7186  const MockRead kProxyConnected(
7187      "HTTP/1.1 200 Connection Established\r\n\r\n");
7188
7189  // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
7190  // no constructors, but the C++ compiler on Windows warns about
7191  // unspecified data in compound literals. So, moved to using constructors,
7192  // and TestRound's created with the default constructor should not be used.
7193  struct TestRound {
7194    TestRound()
7195        : expected_rv(ERR_UNEXPECTED),
7196          extra_write(NULL),
7197          extra_read(NULL) {
7198    }
7199    TestRound(const MockWrite& write_arg, const MockRead& read_arg,
7200              int expected_rv_arg)
7201        : write(write_arg),
7202          read(read_arg),
7203          expected_rv(expected_rv_arg),
7204          extra_write(NULL),
7205          extra_read(NULL) {
7206    }
7207    TestRound(const MockWrite& write_arg, const MockRead& read_arg,
7208              int expected_rv_arg, const MockWrite* extra_write_arg,
7209              const MockWrite* extra_read_arg)
7210        : write(write_arg),
7211          read(read_arg),
7212          expected_rv(expected_rv_arg),
7213          extra_write(extra_write_arg),
7214          extra_read(extra_read_arg) {
7215    }
7216    MockWrite write;
7217    MockRead read;
7218    int expected_rv;
7219    const MockWrite* extra_write;
7220    const MockRead* extra_read;
7221  };
7222
7223  static const int kNoSSL = 500;
7224
7225  struct TestConfig {
7226    const char* proxy_url;
7227    AuthTiming proxy_auth_timing;
7228    int proxy_auth_rv;
7229    const char* server_url;
7230    AuthTiming server_auth_timing;
7231    int server_auth_rv;
7232    int num_auth_rounds;
7233    int first_ssl_round;
7234    TestRound rounds[3];
7235  } test_configs[] = {
7236    // Non-authenticating HTTP server with a direct connection.
7237    { NULL, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
7238      { TestRound(kGet, kSuccess, OK)}},
7239    // Authenticating HTTP server with a direct connection.
7240    { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
7241      { TestRound(kGet, kServerChallenge, OK),
7242        TestRound(kGetAuth, kSuccess, OK)}},
7243    { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
7244      { TestRound(kGet, kServerChallenge, OK),
7245        TestRound(kGetAuth, kFailure, kAuthErr)}},
7246    { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
7247      { TestRound(kGet, kServerChallenge, OK),
7248        TestRound(kGetAuth, kSuccess, OK)}},
7249    { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
7250      { TestRound(kGet, kServerChallenge, OK),
7251        TestRound(kGetAuth, kFailure, kAuthErr)}},
7252    // Non-authenticating HTTP server through a non-authenticating proxy.
7253    { kProxy, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
7254      { TestRound(kGetProxy, kSuccess, OK)}},
7255    // Authenticating HTTP server through a non-authenticating proxy.
7256    { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
7257      { TestRound(kGetProxy, kServerChallenge, OK),
7258        TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
7259    { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
7260      { TestRound(kGetProxy, kServerChallenge, OK),
7261        TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
7262    { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
7263      { TestRound(kGetProxy, kServerChallenge, OK),
7264        TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
7265    { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
7266      { TestRound(kGetProxy, kServerChallenge, OK),
7267        TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
7268    // Non-authenticating HTTP server through an authenticating proxy.
7269    { kProxy, AUTH_SYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
7270      { TestRound(kGetProxy, kProxyChallenge, OK),
7271        TestRound(kGetProxyAuth, kSuccess, OK)}},
7272    { kProxy, AUTH_SYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
7273      { TestRound(kGetProxy, kProxyChallenge, OK),
7274        TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
7275    { kProxy, AUTH_ASYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
7276      { TestRound(kGetProxy, kProxyChallenge, OK),
7277        TestRound(kGetProxyAuth, kSuccess, OK)}},
7278    { kProxy, AUTH_ASYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
7279      { TestRound(kGetProxy, kProxyChallenge, OK),
7280        TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
7281    // Authenticating HTTP server through an authenticating proxy.
7282    { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
7283      { TestRound(kGetProxy, kProxyChallenge, OK),
7284        TestRound(kGetProxyAuth, kServerChallenge, OK),
7285        TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
7286    { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
7287      { TestRound(kGetProxy, kProxyChallenge, OK),
7288        TestRound(kGetProxyAuth, kServerChallenge, OK),
7289        TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
7290    { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
7291      { TestRound(kGetProxy, kProxyChallenge, OK),
7292        TestRound(kGetProxyAuth, kServerChallenge, OK),
7293        TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
7294    { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
7295      { TestRound(kGetProxy, kProxyChallenge, OK),
7296        TestRound(kGetProxyAuth, kServerChallenge, OK),
7297        TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
7298    { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
7299      { TestRound(kGetProxy, kProxyChallenge, OK),
7300        TestRound(kGetProxyAuth, kServerChallenge, OK),
7301        TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
7302    { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
7303      { TestRound(kGetProxy, kProxyChallenge, OK),
7304        TestRound(kGetProxyAuth, kServerChallenge, OK),
7305        TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
7306    { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
7307      { TestRound(kGetProxy, kProxyChallenge, OK),
7308        TestRound(kGetProxyAuth, kServerChallenge, OK),
7309        TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
7310    { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
7311      { TestRound(kGetProxy, kProxyChallenge, OK),
7312        TestRound(kGetProxyAuth, kServerChallenge, OK),
7313        TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
7314    // Non-authenticating HTTPS server with a direct connection.
7315    { NULL, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
7316      { TestRound(kGet, kSuccess, OK)}},
7317    // Authenticating HTTPS server with a direct connection.
7318    { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
7319      { TestRound(kGet, kServerChallenge, OK),
7320        TestRound(kGetAuth, kSuccess, OK)}},
7321    { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
7322      { TestRound(kGet, kServerChallenge, OK),
7323        TestRound(kGetAuth, kFailure, kAuthErr)}},
7324    { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
7325      { TestRound(kGet, kServerChallenge, OK),
7326        TestRound(kGetAuth, kSuccess, OK)}},
7327    { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
7328      { TestRound(kGet, kServerChallenge, OK),
7329        TestRound(kGetAuth, kFailure, kAuthErr)}},
7330    // Non-authenticating HTTPS server with a non-authenticating proxy.
7331    { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
7332      { TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
7333    // Authenticating HTTPS server through a non-authenticating proxy.
7334    { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
7335      { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
7336        TestRound(kGetAuth, kSuccess, OK)}},
7337    { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
7338      { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
7339        TestRound(kGetAuth, kFailure, kAuthErr)}},
7340    { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
7341      { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
7342        TestRound(kGetAuth, kSuccess, OK)}},
7343    { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
7344      { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
7345        TestRound(kGetAuth, kFailure, kAuthErr)}},
7346    // Non-Authenticating HTTPS server through an authenticating proxy.
7347    { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
7348      { TestRound(kConnect, kProxyChallenge, OK),
7349        TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
7350    { kProxy, AUTH_SYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
7351      { TestRound(kConnect, kProxyChallenge, OK),
7352        TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
7353    { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
7354      { TestRound(kConnect, kProxyChallenge, OK),
7355        TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
7356    { kProxy, AUTH_ASYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
7357      { TestRound(kConnect, kProxyChallenge, OK),
7358        TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
7359    // Authenticating HTTPS server through an authenticating proxy.
7360    { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
7361      { TestRound(kConnect, kProxyChallenge, OK),
7362        TestRound(kConnectProxyAuth, kProxyConnected, OK,
7363                  &kGet, &kServerChallenge),
7364        TestRound(kGetAuth, kSuccess, OK)}},
7365    { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
7366      { TestRound(kConnect, kProxyChallenge, OK),
7367        TestRound(kConnectProxyAuth, kProxyConnected, OK,
7368                  &kGet, &kServerChallenge),
7369        TestRound(kGetAuth, kFailure, kAuthErr)}},
7370    { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
7371      { TestRound(kConnect, kProxyChallenge, OK),
7372        TestRound(kConnectProxyAuth, kProxyConnected, OK,
7373                  &kGet, &kServerChallenge),
7374        TestRound(kGetAuth, kSuccess, OK)}},
7375    { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
7376      { TestRound(kConnect, kProxyChallenge, OK),
7377        TestRound(kConnectProxyAuth, kProxyConnected, OK,
7378                  &kGet, &kServerChallenge),
7379        TestRound(kGetAuth, kFailure, kAuthErr)}},
7380    { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
7381      { TestRound(kConnect, kProxyChallenge, OK),
7382        TestRound(kConnectProxyAuth, kProxyConnected, OK,
7383                  &kGet, &kServerChallenge),
7384        TestRound(kGetAuth, kSuccess, OK)}},
7385    { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
7386      { TestRound(kConnect, kProxyChallenge, OK),
7387        TestRound(kConnectProxyAuth, kProxyConnected, OK,
7388                  &kGet, &kServerChallenge),
7389        TestRound(kGetAuth, kFailure, kAuthErr)}},
7390    { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
7391      { TestRound(kConnect, kProxyChallenge, OK),
7392        TestRound(kConnectProxyAuth, kProxyConnected, OK,
7393                  &kGet, &kServerChallenge),
7394        TestRound(kGetAuth, kSuccess, OK)}},
7395    { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
7396      { TestRound(kConnect, kProxyChallenge, OK),
7397        TestRound(kConnectProxyAuth, kProxyConnected, OK,
7398                  &kGet, &kServerChallenge),
7399        TestRound(kGetAuth, kFailure, kAuthErr)}},
7400  };
7401
7402  SessionDependencies session_deps;
7403  HttpAuthHandlerMock::Factory* auth_factory(
7404      new HttpAuthHandlerMock::Factory());
7405  session_deps.http_auth_handler_factory.reset(auth_factory);
7406
7407  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_configs); ++i) {
7408    const TestConfig& test_config = test_configs[i];
7409
7410    // Set up authentication handlers as necessary.
7411    if (test_config.proxy_auth_timing != AUTH_NONE) {
7412      HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
7413      std::string auth_challenge = "Mock realm=proxy";
7414      GURL origin(test_config.proxy_url);
7415      HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
7416                                             auth_challenge.end());
7417      auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_PROXY,
7418                                      origin, BoundNetLog());
7419      auth_handler->SetGenerateExpectation(
7420          test_config.proxy_auth_timing == AUTH_ASYNC,
7421          test_config.proxy_auth_rv);
7422      auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_PROXY);
7423    }
7424    if (test_config.server_auth_timing != AUTH_NONE) {
7425      HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
7426      std::string auth_challenge = "Mock realm=server";
7427      GURL origin(test_config.server_url);
7428      HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
7429                                             auth_challenge.end());
7430      auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
7431                                      origin, BoundNetLog());
7432      auth_handler->SetGenerateExpectation(
7433          test_config.server_auth_timing == AUTH_ASYNC,
7434          test_config.server_auth_rv);
7435      auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_SERVER);
7436    }
7437    if (test_config.proxy_url) {
7438      session_deps.proxy_service =
7439          ProxyService::CreateFixed(test_config.proxy_url);
7440    } else {
7441      session_deps.proxy_service = ProxyService::CreateDirect();
7442    }
7443
7444    HttpRequestInfo request;
7445    request.method = "GET";
7446    request.url = GURL(test_config.server_url);
7447    request.load_flags = 0;
7448
7449    scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7450    HttpNetworkTransaction trans(CreateSession(&session_deps));
7451
7452    for (int round = 0; round < test_config.num_auth_rounds; ++round) {
7453      const TestRound& read_write_round = test_config.rounds[round];
7454
7455      // Set up expected reads and writes.
7456      MockRead reads[2];
7457      reads[0] = read_write_round.read;
7458      size_t length_reads = 1;
7459      if (read_write_round.extra_read) {
7460        reads[1] = *read_write_round.extra_read;
7461        length_reads = 2;
7462      }
7463
7464      MockWrite writes[2];
7465      writes[0] = read_write_round.write;
7466      size_t length_writes = 1;
7467      if (read_write_round.extra_write) {
7468        writes[1] = *read_write_round.extra_write;
7469        length_writes = 2;
7470      }
7471      StaticSocketDataProvider data_provider(
7472          reads, length_reads, writes, length_writes);
7473      session_deps.socket_factory.AddSocketDataProvider(&data_provider);
7474
7475      // Add an SSL sequence if necessary.
7476      SSLSocketDataProvider ssl_socket_data_provider(false, OK);
7477      if (round >= test_config.first_ssl_round)
7478        session_deps.socket_factory.AddSSLSocketDataProvider(
7479            &ssl_socket_data_provider);
7480
7481      // Start or restart the transaction.
7482      TestCompletionCallback callback;
7483      int rv;
7484      if (round == 0) {
7485        rv = trans.Start(&request, &callback, BoundNetLog());
7486      } else {
7487        rv = trans.RestartWithAuth(kFoo, kBar, &callback);
7488      }
7489      if (rv == ERR_IO_PENDING)
7490        rv = callback.WaitForResult();
7491
7492      // Compare results with expected data.
7493      EXPECT_EQ(read_write_round.expected_rv, rv);
7494      const HttpResponseInfo* response = trans.GetResponseInfo();
7495      if (read_write_round.expected_rv == OK) {
7496        EXPECT_FALSE(response == NULL);
7497      } else {
7498        EXPECT_TRUE(response == NULL);
7499        EXPECT_EQ(round + 1, test_config.num_auth_rounds);
7500        continue;
7501      }
7502      if (round + 1 < test_config.num_auth_rounds) {
7503        EXPECT_FALSE(response->auth_challenge.get() == NULL);
7504      } else {
7505        EXPECT_TRUE(response->auth_challenge.get() == NULL);
7506      }
7507    }
7508  }
7509}
7510
7511TEST_F(HttpNetworkTransactionTest, MultiRoundAuth) {
7512  // Do multi-round authentication and make sure it works correctly.
7513  SessionDependencies session_deps;
7514  HttpAuthHandlerMock::Factory* auth_factory(
7515      new HttpAuthHandlerMock::Factory());
7516  session_deps.http_auth_handler_factory.reset(auth_factory);
7517  session_deps.proxy_service = ProxyService::CreateDirect();
7518  session_deps.host_resolver->rules()->AddRule("www.example.com", "10.0.0.1");
7519  session_deps.host_resolver->set_synchronous_mode(true);
7520
7521  HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
7522  auth_handler->set_connection_based(true);
7523  std::string auth_challenge = "Mock realm=server";
7524  GURL origin("http://www.example.com");
7525  HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
7526                                         auth_challenge.end());
7527  auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
7528                                  origin, BoundNetLog());
7529  auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_SERVER);
7530
7531  int rv = OK;
7532  const HttpResponseInfo* response = NULL;
7533  HttpRequestInfo request;
7534  request.method = "GET";
7535  request.url = origin;
7536  request.load_flags = 0;
7537
7538  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7539
7540  // Use a TCP Socket Pool with only one connection per group. This is used
7541  // to validate that the TCP socket is not released to the pool between
7542  // each round of multi-round authentication.
7543  HttpNetworkSessionPeer session_peer(session);
7544  ClientSocketPoolHistograms transport_pool_histograms("SmallTCP");
7545  TransportClientSocketPool* transport_pool = new TransportClientSocketPool(
7546      50,  // Max sockets for pool
7547      1,   // Max sockets per group
7548      &transport_pool_histograms,
7549      session_deps.host_resolver.get(),
7550      &session_deps.socket_factory,
7551      session_deps.net_log);
7552  session_peer.SetTransportSocketPool(transport_pool);
7553
7554  scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
7555  TestCompletionCallback callback;
7556
7557  const MockWrite kGet(
7558      "GET / HTTP/1.1\r\n"
7559      "Host: www.example.com\r\n"
7560      "Connection: keep-alive\r\n\r\n");
7561  const MockWrite kGetAuth(
7562      "GET / HTTP/1.1\r\n"
7563      "Host: www.example.com\r\n"
7564      "Connection: keep-alive\r\n"
7565      "Authorization: auth_token\r\n\r\n");
7566
7567  const MockRead kServerChallenge(
7568      "HTTP/1.1 401 Unauthorized\r\n"
7569      "WWW-Authenticate: Mock realm=server\r\n"
7570      "Content-Type: text/html; charset=iso-8859-1\r\n"
7571      "Content-Length: 14\r\n\r\n"
7572      "Unauthorized\r\n");
7573  const MockRead kSuccess(
7574      "HTTP/1.1 200 OK\r\n"
7575      "Content-Type: text/html; charset=iso-8859-1\r\n"
7576      "Content-Length: 3\r\n\r\n"
7577      "Yes");
7578
7579  MockWrite writes[] = {
7580    // First round
7581    kGet,
7582    // Second round
7583    kGetAuth,
7584    // Third round
7585    kGetAuth,
7586    // Fourth round
7587    kGetAuth,
7588    // Competing request
7589    kGet,
7590  };
7591  MockRead reads[] = {
7592    // First round
7593    kServerChallenge,
7594    // Second round
7595    kServerChallenge,
7596    // Third round
7597    kServerChallenge,
7598    // Fourth round
7599    kSuccess,
7600    // Competing response
7601    kSuccess,
7602  };
7603  StaticSocketDataProvider data_provider(reads, arraysize(reads),
7604                                         writes, arraysize(writes));
7605  session_deps.socket_factory.AddSocketDataProvider(&data_provider);
7606
7607  const char* const kSocketGroup = "www.example.com:80";
7608
7609  // First round of authentication.
7610  auth_handler->SetGenerateExpectation(false, OK);
7611  rv = trans->Start(&request, &callback, BoundNetLog());
7612  if (rv == ERR_IO_PENDING)
7613    rv = callback.WaitForResult();
7614  EXPECT_EQ(OK, rv);
7615  response = trans->GetResponseInfo();
7616  ASSERT_FALSE(response == NULL);
7617  EXPECT_FALSE(response->auth_challenge.get() == NULL);
7618  EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
7619
7620  // In between rounds, another request comes in for the same domain.
7621  // It should not be able to grab the TCP socket that trans has already
7622  // claimed.
7623  scoped_ptr<HttpTransaction> trans_compete(
7624      new HttpNetworkTransaction(session));
7625  TestCompletionCallback callback_compete;
7626  rv = trans_compete->Start(&request, &callback_compete, BoundNetLog());
7627  EXPECT_EQ(ERR_IO_PENDING, rv);
7628  // callback_compete.WaitForResult at this point would stall forever,
7629  // since the HttpNetworkTransaction does not release the request back to
7630  // the pool until after authentication completes.
7631
7632  // Second round of authentication.
7633  auth_handler->SetGenerateExpectation(false, OK);
7634  rv = trans->RestartWithAuth(kFoo, kBar, &callback);
7635  if (rv == ERR_IO_PENDING)
7636    rv = callback.WaitForResult();
7637  EXPECT_EQ(OK, rv);
7638  response = trans->GetResponseInfo();
7639  ASSERT_FALSE(response == NULL);
7640  EXPECT_TRUE(response->auth_challenge.get() == NULL);
7641  EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
7642
7643  // Third round of authentication.
7644  auth_handler->SetGenerateExpectation(false, OK);
7645  rv = trans->RestartWithAuth(string16(), string16(), &callback);
7646  if (rv == ERR_IO_PENDING)
7647    rv = callback.WaitForResult();
7648  EXPECT_EQ(OK, rv);
7649  response = trans->GetResponseInfo();
7650  ASSERT_FALSE(response == NULL);
7651  EXPECT_TRUE(response->auth_challenge.get() == NULL);
7652  EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
7653
7654  // Fourth round of authentication, which completes successfully.
7655  auth_handler->SetGenerateExpectation(false, OK);
7656  rv = trans->RestartWithAuth(string16(), string16(), &callback);
7657  if (rv == ERR_IO_PENDING)
7658    rv = callback.WaitForResult();
7659  EXPECT_EQ(OK, rv);
7660  response = trans->GetResponseInfo();
7661  ASSERT_FALSE(response == NULL);
7662  EXPECT_TRUE(response->auth_challenge.get() == NULL);
7663  EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
7664
7665  // Read the body since the fourth round was successful. This will also
7666  // release the socket back to the pool.
7667  scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(50));
7668  rv = trans->Read(io_buf, io_buf->size(), &callback);
7669  if (rv == ERR_IO_PENDING)
7670    rv = callback.WaitForResult();
7671  EXPECT_EQ(3, rv);
7672  rv = trans->Read(io_buf, io_buf->size(), &callback);
7673  EXPECT_EQ(0, rv);
7674  // There are still 0 idle sockets, since the trans_compete transaction
7675  // will be handed it immediately after trans releases it to the group.
7676  EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
7677
7678  // The competing request can now finish. Wait for the headers and then
7679  // read the body.
7680  rv = callback_compete.WaitForResult();
7681  EXPECT_EQ(OK, rv);
7682  rv = trans_compete->Read(io_buf, io_buf->size(), &callback);
7683  if (rv == ERR_IO_PENDING)
7684    rv = callback.WaitForResult();
7685  EXPECT_EQ(3, rv);
7686  rv = trans_compete->Read(io_buf, io_buf->size(), &callback);
7687  EXPECT_EQ(0, rv);
7688
7689  // Finally, the socket is released to the group.
7690  EXPECT_EQ(1, transport_pool->IdleSocketCountInGroup(kSocketGroup));
7691}
7692
7693class TLSDecompressionFailureSocketDataProvider : public SocketDataProvider {
7694 public:
7695  explicit TLSDecompressionFailureSocketDataProvider(bool fail_all)
7696      : fail_all_(fail_all) {
7697  }
7698
7699  virtual MockRead GetNextRead() {
7700    if (fail_all_)
7701      return MockRead(false /* async */, ERR_SSL_DECOMPRESSION_FAILURE_ALERT);
7702
7703    return MockRead(false /* async */,
7704                    "HTTP/1.1 200 OK\r\nContent-Length: 3\r\n\r\nok.\r\n");
7705  }
7706
7707  virtual MockWriteResult OnWrite(const std::string& data) {
7708    return MockWriteResult(false /* async */, data.size());
7709  }
7710
7711  void Reset() {
7712  }
7713
7714 private:
7715  const bool fail_all_;
7716};
7717
7718// Test that we restart a connection when we see a decompression failure from
7719// the peer during the handshake. (In the real world we'll restart with SSLv3
7720// and we won't offer DEFLATE in that case.)
7721TEST_F(HttpNetworkTransactionTest, RestartAfterTLSDecompressionFailure) {
7722  HttpRequestInfo request;
7723  request.method = "GET";
7724  request.url = GURL("https://tlsdecompressionfailure.example.com/");
7725  request.load_flags = 0;
7726
7727  SessionDependencies session_deps;
7728  TLSDecompressionFailureSocketDataProvider socket_data_provider1(
7729      false /* fail all reads */);
7730  TLSDecompressionFailureSocketDataProvider socket_data_provider2(false);
7731  SSLSocketDataProvider ssl_socket_data_provider1(
7732      false, ERR_SSL_DECOMPRESSION_FAILURE_ALERT);
7733  SSLSocketDataProvider ssl_socket_data_provider2(false, OK);
7734  session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider1);
7735  session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider2);
7736  session_deps.socket_factory.AddSSLSocketDataProvider(
7737      &ssl_socket_data_provider1);
7738  session_deps.socket_factory.AddSSLSocketDataProvider(
7739      &ssl_socket_data_provider2);
7740
7741  // Work around http://crbug.com/37454
7742  StaticSocketDataProvider bug37454_connection;
7743  bug37454_connection.set_connect_data(MockConnect(true, ERR_UNEXPECTED));
7744  session_deps.socket_factory.AddSocketDataProvider(&bug37454_connection);
7745
7746  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7747  scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
7748  TestCompletionCallback callback;
7749
7750  int rv = trans->Start(&request, &callback, BoundNetLog());
7751  EXPECT_EQ(ERR_IO_PENDING, rv);
7752  EXPECT_EQ(OK, callback.WaitForResult());
7753
7754  const HttpResponseInfo* response = trans->GetResponseInfo();
7755  ASSERT_TRUE(response != NULL);
7756  ASSERT_TRUE(response->headers != NULL);
7757  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7758
7759  std::string response_data;
7760  ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7761  EXPECT_EQ("ok.", response_data);
7762}
7763
7764// Test that we restart a connection if we get a decompression failure from the
7765// peer while reading the first bytes from the connection. This occurs when the
7766// peer cannot handle DEFLATE but we're using False Start, so we don't notice
7767// in the handshake.
7768TEST_F(HttpNetworkTransactionTest,
7769       RestartAfterTLSDecompressionFailureWithFalseStart) {
7770  HttpRequestInfo request;
7771  request.method = "GET";
7772  request.url = GURL("https://tlsdecompressionfailure2.example.com/");
7773  request.load_flags = 0;
7774
7775  SessionDependencies session_deps;
7776  TLSDecompressionFailureSocketDataProvider socket_data_provider1(
7777      true /* fail all reads */);
7778  TLSDecompressionFailureSocketDataProvider socket_data_provider2(false);
7779  SSLSocketDataProvider ssl_socket_data_provider1(false, OK);
7780  SSLSocketDataProvider ssl_socket_data_provider2(false, OK);
7781  session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider1);
7782  session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider2);
7783  session_deps.socket_factory.AddSSLSocketDataProvider(
7784      &ssl_socket_data_provider1);
7785  session_deps.socket_factory.AddSSLSocketDataProvider(
7786      &ssl_socket_data_provider2);
7787
7788  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7789  scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
7790  TestCompletionCallback callback;
7791
7792  int rv = trans->Start(&request, &callback, BoundNetLog());
7793  EXPECT_EQ(ERR_IO_PENDING, rv);
7794  EXPECT_EQ(OK, callback.WaitForResult());
7795
7796  const HttpResponseInfo* response = trans->GetResponseInfo();
7797  ASSERT_TRUE(response != NULL);
7798  ASSERT_TRUE(response->headers != NULL);
7799  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7800
7801  std::string response_data;
7802  ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7803  EXPECT_EQ("ok.", response_data);
7804}
7805
7806// This tests the case that a request is issued via http instead of spdy after
7807// npn is negotiated.
7808TEST_F(HttpNetworkTransactionTest, NpnWithHttpOverSSL) {
7809  HttpStreamFactory::set_use_alternate_protocols(true);
7810  HttpStreamFactory::set_next_protos("\x08http/1.1\x07http1.1");
7811  SessionDependencies session_deps;
7812  HttpRequestInfo request;
7813  request.method = "GET";
7814  request.url = GURL("https://www.google.com/");
7815  request.load_flags = 0;
7816
7817  MockWrite data_writes[] = {
7818    MockWrite("GET / HTTP/1.1\r\n"
7819              "Host: www.google.com\r\n"
7820              "Connection: keep-alive\r\n\r\n"),
7821  };
7822
7823  MockRead data_reads[] = {
7824    MockRead("HTTP/1.1 200 OK\r\n"),
7825    MockRead(kAlternateProtocolHttpHeader),
7826    MockRead("hello world"),
7827    MockRead(false, OK),
7828  };
7829
7830  SSLSocketDataProvider ssl(true, OK);
7831  ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
7832  ssl.next_proto = "http/1.1";
7833
7834  session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
7835
7836  StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7837                                data_writes, arraysize(data_writes));
7838  session_deps.socket_factory.AddSocketDataProvider(&data);
7839
7840  TestCompletionCallback callback;
7841
7842  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7843  scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
7844
7845  int rv = trans->Start(&request, &callback, BoundNetLog());
7846
7847  EXPECT_EQ(ERR_IO_PENDING, rv);
7848  EXPECT_EQ(OK, callback.WaitForResult());
7849
7850  const HttpResponseInfo* response = trans->GetResponseInfo();
7851  ASSERT_TRUE(response != NULL);
7852  ASSERT_TRUE(response->headers != NULL);
7853  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7854
7855  std::string response_data;
7856  ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7857  EXPECT_EQ("hello world", response_data);
7858
7859  EXPECT_FALSE(response->was_fetched_via_spdy);
7860  EXPECT_TRUE(response->was_npn_negotiated);
7861
7862  HttpStreamFactory::set_next_protos("");
7863  HttpStreamFactory::set_use_alternate_protocols(false);
7864}
7865
7866TEST_F(HttpNetworkTransactionTest, SpdyPostNPNServerHangup) {
7867  // Simulate the SSL handshake completing with an NPN negotiation
7868  // followed by an immediate server closing of the socket.
7869  // Fix crash:  http://crbug.com/46369
7870  HttpStreamFactory::set_use_alternate_protocols(true);
7871  HttpStreamFactory::set_next_protos(kExpectedNPNString);
7872  SessionDependencies session_deps;
7873
7874  HttpRequestInfo request;
7875  request.method = "GET";
7876  request.url = GURL("https://www.google.com/");
7877  request.load_flags = 0;
7878
7879  SSLSocketDataProvider ssl(true, OK);
7880  ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
7881  ssl.next_proto = "spdy/2";
7882  ssl.was_npn_negotiated = true;
7883  session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
7884
7885  scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
7886  MockWrite spdy_writes[] = { CreateMockWrite(*req) };
7887
7888  MockRead spdy_reads[] = {
7889    MockRead(false, 0, 0)   // Not async - return 0 immediately.
7890  };
7891
7892  scoped_refptr<DelayedSocketData> spdy_data(
7893      new DelayedSocketData(
7894          0,  // don't wait in this case, immediate hangup.
7895          spdy_reads, arraysize(spdy_reads),
7896          spdy_writes, arraysize(spdy_writes)));
7897  session_deps.socket_factory.AddSocketDataProvider(spdy_data);
7898
7899  TestCompletionCallback callback;
7900
7901  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7902  scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
7903
7904  int rv = trans->Start(&request, &callback, BoundNetLog());
7905  EXPECT_EQ(ERR_IO_PENDING, rv);
7906  EXPECT_EQ(ERR_CONNECTION_CLOSED, callback.WaitForResult());
7907
7908  HttpStreamFactory::set_next_protos("");
7909  HttpStreamFactory::set_use_alternate_protocols(false);
7910}
7911
7912TEST_F(HttpNetworkTransactionTest, SpdyAlternateProtocolThroughProxy) {
7913  // This test ensures that the URL passed into the proxy is upgraded
7914  // to https when doing an Alternate Protocol upgrade.
7915  HttpStreamFactory::set_use_alternate_protocols(true);
7916  HttpStreamFactory::set_next_protos(
7917      "\x08http/1.1\x07http1.1\x06spdy/2\x04spdy");
7918
7919  SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
7920  HttpAuthHandlerMock::Factory* auth_factory =
7921      new HttpAuthHandlerMock::Factory();
7922  HttpAuthHandlerMock* auth_handler = new HttpAuthHandlerMock();
7923  auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_PROXY);
7924  auth_factory->set_do_init_from_challenge(true);
7925  session_deps.http_auth_handler_factory.reset(auth_factory);
7926
7927  HttpRequestInfo request;
7928  request.method = "GET";
7929  request.url = GURL("http://www.google.com");
7930  request.load_flags = 0;
7931
7932  // First round goes unauthenticated through the proxy.
7933  MockWrite data_writes_1[] = {
7934    MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
7935              "Host: www.google.com\r\n"
7936              "Proxy-Connection: keep-alive\r\n"
7937              "\r\n"),
7938  };
7939  MockRead data_reads_1[] = {
7940    MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
7941    MockRead("HTTP/1.1 200 OK\r\n"
7942             "Alternate-Protocol: 443:npn-spdy/2\r\n"
7943             "Proxy-Connection: close\r\n"
7944             "\r\n"),
7945  };
7946  StaticSocketDataProvider data_1(data_reads_1, arraysize(data_reads_1),
7947                                  data_writes_1, arraysize(data_writes_1));
7948
7949  // Second round tries to tunnel to www.google.com due to the
7950  // Alternate-Protocol announcement in the first round. It fails due
7951  // to a proxy authentication challenge.
7952  // After the failure, a tunnel is established to www.google.com using
7953  // Proxy-Authorization headers. There is then a SPDY request round.
7954  //
7955  // NOTE: Despite the "Proxy-Connection: Close", these are done on the
7956  // same MockTCPClientSocket since the underlying HttpNetworkClientSocket
7957  // does a Disconnect and Connect on the same socket, rather than trying
7958  // to obtain a new one.
7959  //
7960  // NOTE: Originally, the proxy response to the second CONNECT request
7961  // simply returned another 407 so the unit test could skip the SSL connection
7962  // establishment and SPDY framing issues. Alas, the
7963  // retry-http-when-alternate-protocol fails logic kicks in, which was more
7964  // complicated to set up expectations for than the SPDY session.
7965
7966  scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
7967  scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
7968  scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
7969
7970  MockWrite data_writes_2[] = {
7971    // First connection attempt without Proxy-Authorization.
7972    MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
7973              "Host: www.google.com\r\n"
7974              "Proxy-Connection: keep-alive\r\n"
7975              "\r\n"),
7976
7977    // Second connection attempt with Proxy-Authorization.
7978    MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
7979              "Host: www.google.com\r\n"
7980              "Proxy-Connection: keep-alive\r\n"
7981              "Proxy-Authorization: auth_token\r\n"
7982              "\r\n"),
7983
7984    // SPDY request
7985    CreateMockWrite(*req),
7986  };
7987  const char kRejectConnectResponse[] = ("HTTP/1.1 407 Unauthorized\r\n"
7988                                         "Proxy-Authenticate: Mock\r\n"
7989                                         "Proxy-Connection: close\r\n"
7990                                         "\r\n");
7991  const char kAcceptConnectResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
7992  MockRead data_reads_2[] = {
7993    // First connection attempt fails
7994    MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ, 1),
7995    MockRead(true, kRejectConnectResponse,
7996             arraysize(kRejectConnectResponse) - 1, 1),
7997
7998    // Second connection attempt passes
7999    MockRead(true, kAcceptConnectResponse,
8000             arraysize(kAcceptConnectResponse) -1, 4),
8001
8002    // SPDY response
8003    CreateMockRead(*resp.get(), 6),
8004    CreateMockRead(*data.get(), 6),
8005    MockRead(true, 0, 0, 6),
8006  };
8007  scoped_refptr<OrderedSocketData> data_2(
8008      new OrderedSocketData(data_reads_2, arraysize(data_reads_2),
8009                            data_writes_2, arraysize(data_writes_2)));
8010
8011  SSLSocketDataProvider ssl(true, OK);
8012  ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
8013  ssl.next_proto = "spdy/2";
8014  ssl.was_npn_negotiated = true;
8015
8016  MockConnect never_finishing_connect(false, ERR_IO_PENDING);
8017  StaticSocketDataProvider hanging_non_alternate_protocol_socket(
8018      NULL, 0, NULL, 0);
8019  hanging_non_alternate_protocol_socket.set_connect_data(
8020      never_finishing_connect);
8021
8022  session_deps.socket_factory.AddSocketDataProvider(&data_1);
8023  session_deps.socket_factory.AddSocketDataProvider(data_2.get());
8024  session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
8025  session_deps.socket_factory.AddSocketDataProvider(
8026      &hanging_non_alternate_protocol_socket);
8027  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8028
8029  // First round should work and provide the Alternate-Protocol state.
8030  TestCompletionCallback callback_1;
8031  scoped_ptr<HttpTransaction> trans_1(new HttpNetworkTransaction(session));
8032  int rv = trans_1->Start(&request, &callback_1, BoundNetLog());
8033  EXPECT_EQ(ERR_IO_PENDING, rv);
8034  EXPECT_EQ(OK, callback_1.WaitForResult());
8035
8036  // Second round should attempt a tunnel connect and get an auth challenge.
8037  TestCompletionCallback callback_2;
8038  scoped_ptr<HttpTransaction> trans_2(new HttpNetworkTransaction(session));
8039  rv = trans_2->Start(&request, &callback_2, BoundNetLog());
8040  EXPECT_EQ(ERR_IO_PENDING, rv);
8041  EXPECT_EQ(OK, callback_2.WaitForResult());
8042  const HttpResponseInfo* response = trans_2->GetResponseInfo();
8043  ASSERT_FALSE(response == NULL);
8044  ASSERT_FALSE(response->auth_challenge.get() == NULL);
8045
8046  // Restart with auth. Tunnel should work and response received.
8047  TestCompletionCallback callback_3;
8048  rv = trans_2->RestartWithAuth(kFoo, kBar, &callback_3);
8049  EXPECT_EQ(ERR_IO_PENDING, rv);
8050  EXPECT_EQ(OK, callback_3.WaitForResult());
8051
8052  // After all that work, these two lines (or actually, just the scheme) are
8053  // what this test is all about. Make sure it happens correctly.
8054  const GURL& request_url = auth_handler->request_url();
8055  EXPECT_EQ("https", request_url.scheme());
8056  EXPECT_EQ("www.google.com", request_url.host());
8057
8058  HttpStreamFactory::set_next_protos("");
8059  HttpStreamFactory::set_use_alternate_protocols(false);
8060}
8061
8062// Test that if we cancel the transaction as the connection is completing, that
8063// everything tears down correctly.
8064TEST_F(HttpNetworkTransactionTest, SimpleCancel) {
8065  // Setup everything about the connection to complete synchronously, so that
8066  // after calling HttpNetworkTransaction::Start, the only thing we're waiting
8067  // for is the callback from the HttpStreamRequest.
8068  // Then cancel the transaction.
8069  // Verify that we don't crash.
8070  MockConnect mock_connect(false, OK);
8071  MockRead data_reads[] = {
8072    MockRead(false, "HTTP/1.0 200 OK\r\n\r\n"),
8073    MockRead(false, "hello world"),
8074    MockRead(false, OK),
8075  };
8076
8077  HttpRequestInfo request;
8078  request.method = "GET";
8079  request.url = GURL("http://www.google.com/");
8080  request.load_flags = 0;
8081
8082  SessionDependencies session_deps;
8083  session_deps.host_resolver->set_synchronous_mode(true);
8084  scoped_ptr<HttpTransaction> trans(
8085      new HttpNetworkTransaction(CreateSession(&session_deps)));
8086
8087  StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
8088  data.set_connect_data(mock_connect);
8089  session_deps.socket_factory.AddSocketDataProvider(&data);
8090
8091  TestCompletionCallback callback;
8092
8093  CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
8094  int rv = trans->Start(&request, &callback, log.bound());
8095  EXPECT_EQ(ERR_IO_PENDING, rv);
8096  trans.reset();  // Cancel the transaction here.
8097
8098  MessageLoop::current()->RunAllPending();
8099}
8100
8101// Test a basic GET request through a proxy.
8102TEST_F(HttpNetworkTransactionTest, ProxyGet) {
8103  SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
8104  CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
8105  session_deps.net_log = log.bound().net_log();
8106  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8107
8108  HttpRequestInfo request;
8109  request.method = "GET";
8110  request.url = GURL("http://www.google.com/");
8111
8112  MockWrite data_writes1[] = {
8113    MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
8114              "Host: www.google.com\r\n"
8115              "Proxy-Connection: keep-alive\r\n\r\n"),
8116  };
8117
8118  MockRead data_reads1[] = {
8119    MockRead("HTTP/1.1 200 OK\r\n"),
8120    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8121    MockRead("Content-Length: 100\r\n\r\n"),
8122    MockRead(false, OK),
8123  };
8124
8125  StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
8126                                 data_writes1, arraysize(data_writes1));
8127  session_deps.socket_factory.AddSocketDataProvider(&data1);
8128
8129  TestCompletionCallback callback1;
8130
8131  scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
8132
8133  int rv = trans->Start(&request, &callback1, log.bound());
8134  EXPECT_EQ(ERR_IO_PENDING, rv);
8135
8136  rv = callback1.WaitForResult();
8137  EXPECT_EQ(OK, rv);
8138
8139  const HttpResponseInfo* response = trans->GetResponseInfo();
8140  ASSERT_FALSE(response == NULL);
8141
8142  EXPECT_TRUE(response->headers->IsKeepAlive());
8143  EXPECT_EQ(200, response->headers->response_code());
8144  EXPECT_EQ(100, response->headers->GetContentLength());
8145  EXPECT_TRUE(response->was_fetched_via_proxy);
8146  EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
8147}
8148
8149// Test a basic HTTPS GET request through a proxy.
8150TEST_F(HttpNetworkTransactionTest, ProxyTunnelGet) {
8151  SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
8152  CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
8153  session_deps.net_log = log.bound().net_log();
8154  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8155
8156  HttpRequestInfo request;
8157  request.method = "GET";
8158  request.url = GURL("https://www.google.com/");
8159
8160  // Since we have proxy, should try to establish tunnel.
8161  MockWrite data_writes1[] = {
8162    MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
8163              "Host: www.google.com\r\n"
8164              "Proxy-Connection: keep-alive\r\n\r\n"),
8165
8166    MockWrite("GET / HTTP/1.1\r\n"
8167              "Host: www.google.com\r\n"
8168              "Connection: keep-alive\r\n\r\n"),
8169  };
8170
8171  MockRead data_reads1[] = {
8172    MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
8173
8174    MockRead("HTTP/1.1 200 OK\r\n"),
8175    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8176    MockRead("Content-Length: 100\r\n\r\n"),
8177    MockRead(false, OK),
8178  };
8179
8180  StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
8181                                 data_writes1, arraysize(data_writes1));
8182  session_deps.socket_factory.AddSocketDataProvider(&data1);
8183  SSLSocketDataProvider ssl(true, OK);
8184  session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
8185
8186  TestCompletionCallback callback1;
8187
8188  scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
8189
8190  int rv = trans->Start(&request, &callback1, log.bound());
8191  EXPECT_EQ(ERR_IO_PENDING, rv);
8192
8193  rv = callback1.WaitForResult();
8194  EXPECT_EQ(OK, rv);
8195  net::CapturingNetLog::EntryList entries;
8196  log.GetEntries(&entries);
8197  size_t pos = ExpectLogContainsSomewhere(
8198      entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
8199      NetLog::PHASE_NONE);
8200  ExpectLogContainsSomewhere(
8201      entries, pos,
8202      NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
8203      NetLog::PHASE_NONE);
8204
8205  const HttpResponseInfo* response = trans->GetResponseInfo();
8206  ASSERT_FALSE(response == NULL);
8207
8208  EXPECT_TRUE(response->headers->IsKeepAlive());
8209  EXPECT_EQ(200, response->headers->response_code());
8210  EXPECT_EQ(100, response->headers->GetContentLength());
8211  EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
8212  EXPECT_TRUE(response->was_fetched_via_proxy);
8213}
8214
8215// Test a basic HTTPS GET request through a proxy, but the server hangs up
8216// while establishing the tunnel.
8217TEST_F(HttpNetworkTransactionTest, ProxyTunnelGetHangup) {
8218  SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
8219  CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
8220  session_deps.net_log = log.bound().net_log();
8221  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8222
8223  HttpRequestInfo request;
8224  request.method = "GET";
8225  request.url = GURL("https://www.google.com/");
8226
8227  // Since we have proxy, should try to establish tunnel.
8228  MockWrite data_writes1[] = {
8229    MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
8230              "Host: www.google.com\r\n"
8231              "Proxy-Connection: keep-alive\r\n\r\n"),
8232
8233    MockWrite("GET / HTTP/1.1\r\n"
8234              "Host: www.google.com\r\n"
8235              "Connection: keep-alive\r\n\r\n"),
8236  };
8237
8238  MockRead data_reads1[] = {
8239    MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
8240    MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
8241    MockRead(true, 0, 0),  // EOF
8242  };
8243
8244  StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
8245                                 data_writes1, arraysize(data_writes1));
8246  session_deps.socket_factory.AddSocketDataProvider(&data1);
8247  SSLSocketDataProvider ssl(true, OK);
8248  session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
8249
8250  TestCompletionCallback callback1;
8251
8252  scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
8253
8254  int rv = trans->Start(&request, &callback1, log.bound());
8255  EXPECT_EQ(ERR_IO_PENDING, rv);
8256
8257  rv = callback1.WaitForResult();
8258  EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
8259  net::CapturingNetLog::EntryList entries;
8260  log.GetEntries(&entries);
8261  size_t pos = ExpectLogContainsSomewhere(
8262      entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
8263      NetLog::PHASE_NONE);
8264  ExpectLogContainsSomewhere(
8265      entries, pos,
8266      NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
8267      NetLog::PHASE_NONE);
8268}
8269
8270// Test for crbug.com/55424.
8271TEST_F(HttpNetworkTransactionTest, PreconnectWithExistingSpdySession) {
8272  SessionDependencies session_deps;
8273
8274  scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(
8275      "https://www.google.com", false, 1, LOWEST));
8276  MockWrite spdy_writes[] = { CreateMockWrite(*req) };
8277
8278  scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
8279  scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
8280  MockRead spdy_reads[] = {
8281    CreateMockRead(*resp),
8282    CreateMockRead(*data),
8283    MockRead(true, 0, 0),
8284  };
8285
8286  scoped_refptr<DelayedSocketData> spdy_data(
8287      new DelayedSocketData(
8288          1,  // wait for one write to finish before reading.
8289          spdy_reads, arraysize(spdy_reads),
8290          spdy_writes, arraysize(spdy_writes)));
8291  session_deps.socket_factory.AddSocketDataProvider(spdy_data);
8292
8293  SSLSocketDataProvider ssl(true, OK);
8294  ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
8295  ssl.next_proto = "spdy/2";
8296  ssl.was_npn_negotiated = true;
8297  session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
8298
8299  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8300
8301  // Set up an initial SpdySession in the pool to reuse.
8302  HostPortPair host_port_pair("www.google.com", 443);
8303  HostPortProxyPair pair(host_port_pair, ProxyServer::Direct());
8304  scoped_refptr<SpdySession> spdy_session =
8305      session->spdy_session_pool()->Get(pair, BoundNetLog());
8306  scoped_refptr<TransportSocketParams> transport_params(
8307      new TransportSocketParams(host_port_pair, MEDIUM, GURL(), false, false));
8308  TestCompletionCallback callback;
8309
8310  scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle);
8311  EXPECT_EQ(ERR_IO_PENDING,
8312            connection->Init(host_port_pair.ToString(), transport_params,
8313                             LOWEST, &callback,
8314                             session->transport_socket_pool(), BoundNetLog()));
8315  EXPECT_EQ(OK, callback.WaitForResult());
8316  spdy_session->InitializeWithSocket(connection.release(), false, OK);
8317
8318  HttpRequestInfo request;
8319  request.method = "GET";
8320  request.url = GURL("https://www.google.com/");
8321  request.load_flags = 0;
8322
8323  // This is the important line that marks this as a preconnect.
8324  request.motivation = HttpRequestInfo::PRECONNECT_MOTIVATED;
8325
8326  scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
8327
8328  int rv = trans->Start(&request, &callback, BoundNetLog());
8329  EXPECT_EQ(ERR_IO_PENDING, rv);
8330  EXPECT_EQ(OK, callback.WaitForResult());
8331}
8332
8333// Given a net error, cause that error to be returned from the first Write()
8334// call and verify that the HttpTransaction fails with that error.
8335static void CheckErrorIsPassedBack(int error, bool async) {
8336  net::HttpRequestInfo request_info;
8337  request_info.url = GURL("https://www.example.com/");
8338  request_info.method = "GET";
8339  request_info.load_flags = net::LOAD_NORMAL;
8340
8341  SessionDependencies session_deps;
8342
8343  SSLSocketDataProvider ssl_data(async, OK);
8344  net::MockWrite data_writes[] = {
8345    net::MockWrite(async, error),
8346  };
8347  net::StaticSocketDataProvider data(NULL, 0,
8348                                     data_writes, arraysize(data_writes));
8349  session_deps.socket_factory.AddSocketDataProvider(&data);
8350  session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data);
8351
8352  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8353  scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
8354
8355  TestCompletionCallback callback;
8356  int rv = trans->Start(&request_info, &callback, net::BoundNetLog());
8357  if (rv == net::ERR_IO_PENDING)
8358    rv = callback.WaitForResult();
8359  ASSERT_EQ(error, rv);
8360}
8361
8362TEST_F(HttpNetworkTransactionTest, SSLWriteCertError) {
8363  // Just check a grab bag of cert errors.
8364  static const int kErrors[] = {
8365    ERR_CERT_COMMON_NAME_INVALID,
8366    ERR_CERT_AUTHORITY_INVALID,
8367    ERR_CERT_DATE_INVALID,
8368  };
8369  for (size_t i = 0; i < arraysize(kErrors); i++) {
8370    CheckErrorIsPassedBack(kErrors[i], false /* not async */);
8371    CheckErrorIsPassedBack(kErrors[i], true /* async */);
8372  }
8373}
8374
8375// Ensure that a client certificate is removed from the SSL client auth
8376// cache when:
8377//  1) No proxy is involved.
8378//  2) TLS False Start is disabled.
8379//  3) The initial TLS handshake requests a client certificate.
8380//  4) The client supplies an invalid/unacceptable certificate.
8381TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Direct_NoFalseStart) {
8382  net::HttpRequestInfo request_info;
8383  request_info.url = GURL("https://www.example.com/");
8384  request_info.method = "GET";
8385  request_info.load_flags = net::LOAD_NORMAL;
8386
8387  SessionDependencies session_deps;
8388
8389  scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
8390  cert_request->host_and_port = "www.example.com:443";
8391
8392  // [ssl_]data1 contains the data for the first SSL handshake. When a
8393  // CertificateRequest is received for the first time, the handshake will
8394  // be aborted to allow the caller to provide a certificate.
8395  SSLSocketDataProvider ssl_data1(true /* async */,
8396                                  net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
8397  ssl_data1.cert_request_info = cert_request.get();
8398  session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data1);
8399  net::StaticSocketDataProvider data1(NULL, 0, NULL, 0);
8400  session_deps.socket_factory.AddSocketDataProvider(&data1);
8401
8402  // [ssl_]data2 contains the data for the second SSL handshake. When TLS
8403  // False Start is not being used, the result of the SSL handshake will be
8404  // returned as part of the SSLClientSocket::Connect() call. This test
8405  // matches the result of a server sending a handshake_failure alert,
8406  // rather than a Finished message, because it requires a client
8407  // certificate and none was supplied.
8408  SSLSocketDataProvider ssl_data2(true /* async */,
8409                                  net::ERR_SSL_PROTOCOL_ERROR);
8410  ssl_data2.cert_request_info = cert_request.get();
8411  session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data2);
8412  net::StaticSocketDataProvider data2(NULL, 0, NULL, 0);
8413  session_deps.socket_factory.AddSocketDataProvider(&data2);
8414
8415  // [ssl_]data3 contains the data for the third SSL handshake. When a
8416  // connection to a server fails during an SSL handshake,
8417  // HttpNetworkTransaction will attempt to fallback to SSLv3 if the initial
8418  // connection was attempted with TLSv1. This is transparent to the caller
8419  // of the HttpNetworkTransaction. Because this test failure is due to
8420  // requiring a client certificate, this fallback handshake should also
8421  // fail.
8422  SSLSocketDataProvider ssl_data3(true /* async */,
8423                                  net::ERR_SSL_PROTOCOL_ERROR);
8424  ssl_data3.cert_request_info = cert_request.get();
8425  session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data3);
8426  net::StaticSocketDataProvider data3(NULL, 0, NULL, 0);
8427  session_deps.socket_factory.AddSocketDataProvider(&data3);
8428
8429  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8430  scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
8431
8432  // Begin the SSL handshake with the peer. This consumes ssl_data1.
8433  TestCompletionCallback callback;
8434  int rv = trans->Start(&request_info, &callback, net::BoundNetLog());
8435  ASSERT_EQ(net::ERR_IO_PENDING, rv);
8436
8437  // Complete the SSL handshake, which should abort due to requiring a
8438  // client certificate.
8439  rv = callback.WaitForResult();
8440  ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
8441
8442  // Indicate that no certificate should be supplied. From the perspective
8443  // of SSLClientCertCache, NULL is just as meaningful as a real
8444  // certificate, so this is the same as supply a
8445  // legitimate-but-unacceptable certificate.
8446  rv = trans->RestartWithCertificate(NULL, &callback);
8447  ASSERT_EQ(net::ERR_IO_PENDING, rv);
8448
8449  // Ensure the certificate was added to the client auth cache before
8450  // allowing the connection to continue restarting.
8451  scoped_refptr<X509Certificate> client_cert;
8452  ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8453                                                       &client_cert));
8454  ASSERT_EQ(NULL, client_cert.get());
8455
8456  // Restart the handshake. This will consume ssl_data2, which fails, and
8457  // then consume ssl_data3, which should also fail. The result code is
8458  // checked against what ssl_data3 should return.
8459  rv = callback.WaitForResult();
8460  ASSERT_EQ(net::ERR_SSL_PROTOCOL_ERROR, rv);
8461
8462  // Ensure that the client certificate is removed from the cache on a
8463  // handshake failure.
8464  ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8465                                                        &client_cert));
8466}
8467
8468// Ensure that a client certificate is removed from the SSL client auth
8469// cache when:
8470//  1) No proxy is involved.
8471//  2) TLS False Start is enabled.
8472//  3) The initial TLS handshake requests a client certificate.
8473//  4) The client supplies an invalid/unacceptable certificate.
8474TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Direct_FalseStart) {
8475  net::HttpRequestInfo request_info;
8476  request_info.url = GURL("https://www.example.com/");
8477  request_info.method = "GET";
8478  request_info.load_flags = net::LOAD_NORMAL;
8479
8480  SessionDependencies session_deps;
8481
8482  scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
8483  cert_request->host_and_port = "www.example.com:443";
8484
8485  // When TLS False Start is used, SSLClientSocket::Connect() calls will
8486  // return successfully after reading up to the peer's Certificate message.
8487  // This is to allow the caller to call SSLClientSocket::Write(), which can
8488  // enqueue application data to be sent in the same packet as the
8489  // ChangeCipherSpec and Finished messages.
8490  // The actual handshake will be finished when SSLClientSocket::Read() is
8491  // called, which expects to process the peer's ChangeCipherSpec and
8492  // Finished messages. If there was an error negotiating with the peer,
8493  // such as due to the peer requiring a client certificate when none was
8494  // supplied, the alert sent by the peer won't be processed until Read() is
8495  // called.
8496
8497  // Like the non-False Start case, when a client certificate is requested by
8498  // the peer, the handshake is aborted during the Connect() call.
8499  // [ssl_]data1 represents the initial SSL handshake with the peer.
8500  SSLSocketDataProvider ssl_data1(true /* async */,
8501                                  net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
8502  ssl_data1.cert_request_info = cert_request.get();
8503  session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data1);
8504  net::StaticSocketDataProvider data1(NULL, 0, NULL, 0);
8505  session_deps.socket_factory.AddSocketDataProvider(&data1);
8506
8507  // When a client certificate is supplied, Connect() will not be aborted
8508  // when the peer requests the certificate. Instead, the handshake will
8509  // artificially succeed, allowing the caller to write the HTTP request to
8510  // the socket. The handshake messages are not processed until Read() is
8511  // called, which then detects that the handshake was aborted, due to the
8512  // peer sending a handshake_failure because it requires a client
8513  // certificate.
8514  SSLSocketDataProvider ssl_data2(true /* async */, net::OK);
8515  ssl_data2.cert_request_info = cert_request.get();
8516  session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data2);
8517  net::MockRead data2_reads[] = {
8518    net::MockRead(true /* async */, net::ERR_SSL_PROTOCOL_ERROR),
8519  };
8520  net::StaticSocketDataProvider data2(
8521      data2_reads, arraysize(data2_reads), NULL, 0);
8522  session_deps.socket_factory.AddSocketDataProvider(&data2);
8523
8524  // As described in ClientAuthCertCache_Direct_NoFalseStart, [ssl_]data3 is
8525  // the data for the SSL handshake once the TLSv1 connection falls back to
8526  // SSLv3. It has the same behaviour as [ssl_]data2.
8527  SSLSocketDataProvider ssl_data3(true /* async */, net::OK);
8528  ssl_data3.cert_request_info = cert_request.get();
8529  session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data3);
8530  net::StaticSocketDataProvider data3(
8531      data2_reads, arraysize(data2_reads), NULL, 0);
8532  session_deps.socket_factory.AddSocketDataProvider(&data3);
8533
8534  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8535  scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
8536
8537  // Begin the initial SSL handshake.
8538  TestCompletionCallback callback;
8539  int rv = trans->Start(&request_info, &callback, net::BoundNetLog());
8540  ASSERT_EQ(net::ERR_IO_PENDING, rv);
8541
8542  // Complete the SSL handshake, which should abort due to requiring a
8543  // client certificate.
8544  rv = callback.WaitForResult();
8545  ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
8546
8547  // Indicate that no certificate should be supplied. From the perspective
8548  // of SSLClientCertCache, NULL is just as meaningful as a real
8549  // certificate, so this is the same as supply a
8550  // legitimate-but-unacceptable certificate.
8551  rv = trans->RestartWithCertificate(NULL, &callback);
8552  ASSERT_EQ(net::ERR_IO_PENDING, rv);
8553
8554  // Ensure the certificate was added to the client auth cache before
8555  // allowing the connection to continue restarting.
8556  scoped_refptr<X509Certificate> client_cert;
8557  ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8558                                                       &client_cert));
8559  ASSERT_EQ(NULL, client_cert.get());
8560
8561
8562  // Restart the handshake. This will consume ssl_data2, which fails, and
8563  // then consume ssl_data3, which should also fail. The result code is
8564  // checked against what ssl_data3 should return.
8565  rv = callback.WaitForResult();
8566  ASSERT_EQ(net::ERR_SSL_PROTOCOL_ERROR, rv);
8567
8568  // Ensure that the client certificate is removed from the cache on a
8569  // handshake failure.
8570  ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8571                                                        &client_cert));
8572}
8573
8574// Ensure that a client certificate is removed from the SSL client auth
8575// cache when:
8576//  1) An HTTPS proxy is involved.
8577//  3) The HTTPS proxy requests a client certificate.
8578//  4) The client supplies an invalid/unacceptable certificate for the
8579//     proxy.
8580// The test is repeated twice, first for connecting to an HTTPS endpoint,
8581// then for connecting to an HTTP endpoint.
8582TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Proxy_Fail) {
8583  SessionDependencies session_deps(
8584      ProxyService::CreateFixed("https://proxy:70"));
8585  CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
8586  session_deps.net_log = log.bound().net_log();
8587
8588  scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
8589  cert_request->host_and_port = "proxy:70";
8590
8591  // See ClientAuthCertCache_Direct_NoFalseStart for the explanation of
8592  // [ssl_]data[1-3]. Rather than represending the endpoint
8593  // (www.example.com:443), they represent failures with the HTTPS proxy
8594  // (proxy:70).
8595  SSLSocketDataProvider ssl_data1(true /* async */,
8596                                  net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
8597  ssl_data1.cert_request_info = cert_request.get();
8598  session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data1);
8599  net::StaticSocketDataProvider data1(NULL, 0, NULL, 0);
8600  session_deps.socket_factory.AddSocketDataProvider(&data1);
8601
8602  SSLSocketDataProvider ssl_data2(true /* async */,
8603                                  net::ERR_SSL_PROTOCOL_ERROR);
8604  ssl_data2.cert_request_info = cert_request.get();
8605  session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data2);
8606  net::StaticSocketDataProvider data2(NULL, 0, NULL, 0);
8607  session_deps.socket_factory.AddSocketDataProvider(&data2);
8608
8609  SSLSocketDataProvider ssl_data3(true /* async */,
8610                                  net::ERR_SSL_PROTOCOL_ERROR);
8611  ssl_data3.cert_request_info = cert_request.get();
8612  session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data3);
8613  net::StaticSocketDataProvider data3(NULL, 0, NULL, 0);
8614  session_deps.socket_factory.AddSocketDataProvider(&data3);
8615
8616  net::HttpRequestInfo requests[2];
8617  requests[0].url = GURL("https://www.example.com/");
8618  requests[0].method = "GET";
8619  requests[0].load_flags = net::LOAD_NORMAL;
8620
8621  requests[1].url = GURL("http://www.example.com/");
8622  requests[1].method = "GET";
8623  requests[1].load_flags = net::LOAD_NORMAL;
8624
8625  for (size_t i = 0; i < arraysize(requests); ++i) {
8626    session_deps.socket_factory.ResetNextMockIndexes();
8627    scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8628    scoped_ptr<HttpNetworkTransaction> trans(
8629        new HttpNetworkTransaction(session));
8630
8631    // Begin the SSL handshake with the proxy.
8632    TestCompletionCallback callback;
8633    int rv = trans->Start(&requests[i], &callback, net::BoundNetLog());
8634    ASSERT_EQ(net::ERR_IO_PENDING, rv);
8635
8636    // Complete the SSL handshake, which should abort due to requiring a
8637    // client certificate.
8638    rv = callback.WaitForResult();
8639    ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
8640
8641    // Indicate that no certificate should be supplied. From the perspective
8642    // of SSLClientCertCache, NULL is just as meaningful as a real
8643    // certificate, so this is the same as supply a
8644    // legitimate-but-unacceptable certificate.
8645    rv = trans->RestartWithCertificate(NULL, &callback);
8646    ASSERT_EQ(net::ERR_IO_PENDING, rv);
8647
8648    // Ensure the certificate was added to the client auth cache before
8649    // allowing the connection to continue restarting.
8650    scoped_refptr<X509Certificate> client_cert;
8651    ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup("proxy:70",
8652                                                         &client_cert));
8653    ASSERT_EQ(NULL, client_cert.get());
8654    // Ensure the certificate was NOT cached for the endpoint. This only
8655    // applies to HTTPS requests, but is fine to check for HTTP requests.
8656    ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8657                                                          &client_cert));
8658
8659    // Restart the handshake. This will consume ssl_data2, which fails, and
8660    // then consume ssl_data3, which should also fail. The result code is
8661    // checked against what ssl_data3 should return.
8662    rv = callback.WaitForResult();
8663    ASSERT_EQ(net::ERR_PROXY_CONNECTION_FAILED, rv);
8664
8665    // Now that the new handshake has failed, ensure that the client
8666    // certificate was removed from the client auth cache.
8667    ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("proxy:70",
8668                                                          &client_cert));
8669    ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8670                                                          &client_cert));
8671  }
8672}
8673
8674}  // namespace net
8675