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