• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2009 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 <math.h>  // ceil
6 
7 #include "base/compiler_specific.h"
8 #include "net/base/completion_callback.h"
9 #include "net/base/mock_host_resolver.h"
10 #include "net/base/request_priority.h"
11 #include "net/base/ssl_config_service_defaults.h"
12 #include "net/base/ssl_info.h"
13 #include "net/base/test_completion_callback.h"
14 #include "net/base/upload_data.h"
15 #include "net/flip/flip_session_pool.h"
16 #include "net/http/http_auth_handler_ntlm.h"
17 #include "net/http/http_basic_stream.h"
18 #include "net/http/http_network_session.h"
19 #include "net/http/http_network_transaction.h"
20 #include "net/http/http_stream.h"
21 #include "net/http/http_transaction_unittest.h"
22 #include "net/proxy/proxy_config_service_fixed.h"
23 #include "net/socket/client_socket_factory.h"
24 #include "net/socket/socket_test_util.h"
25 #include "net/socket/ssl_client_socket.h"
26 #include "testing/gtest/include/gtest/gtest.h"
27 #include "testing/platform_test.h"
28 
29 //-----------------------------------------------------------------------------
30 
31 // TODO(eroman): Add a regression test for http://crbug.com/32316 -- when the
32 // proxy service returns an error, we should fallback to DIRECT instead of
33 // failing with ERR_NO_SUPPORTED_PROXIES.
34 
35 namespace net {
36 
37 // Create a proxy service which fails on all requests (falls back to direct).
CreateNullProxyService()38 ProxyService* CreateNullProxyService() {
39   return ProxyService::CreateNull();
40 }
41 
42 // Helper to manage the lifetimes of the dependencies for a
43 // HttpNetworkTransaction.
44 class SessionDependencies {
45  public:
46   // Default set of dependencies -- "null" proxy service.
SessionDependencies()47   SessionDependencies()
48       : host_resolver(new MockHostResolver),
49         proxy_service(CreateNullProxyService()),
50         ssl_config_service(new SSLConfigServiceDefaults),
51         flip_session_pool(new FlipSessionPool) {}
52 
53   // Custom proxy service dependency.
SessionDependencies(ProxyService * proxy_service)54   explicit SessionDependencies(ProxyService* proxy_service)
55       : host_resolver(new MockHostResolver),
56         proxy_service(proxy_service),
57         ssl_config_service(new SSLConfigServiceDefaults),
58         flip_session_pool(new FlipSessionPool) {}
59 
60   scoped_refptr<MockHostResolverBase> host_resolver;
61   scoped_refptr<ProxyService> proxy_service;
62   scoped_refptr<SSLConfigService> ssl_config_service;
63   MockClientSocketFactory socket_factory;
64   scoped_refptr<FlipSessionPool> flip_session_pool;
65 };
66 
CreateFixedProxyService(const std::string & proxy)67 ProxyService* CreateFixedProxyService(const std::string& proxy) {
68   net::ProxyConfig proxy_config;
69   proxy_config.proxy_rules.ParseFromString(proxy);
70   return ProxyService::CreateFixed(proxy_config);
71 }
72 
73 
CreateSession(SessionDependencies * session_deps)74 HttpNetworkSession* CreateSession(SessionDependencies* session_deps) {
75   return new HttpNetworkSession(NULL,
76                                 session_deps->host_resolver,
77                                 session_deps->proxy_service,
78                                 &session_deps->socket_factory,
79                                 session_deps->ssl_config_service,
80                                 session_deps->flip_session_pool);
81 }
82 
83 class HttpNetworkTransactionTest : public PlatformTest {
84  public:
TearDown()85   virtual void TearDown() {
86     // Empty the current queue.
87     MessageLoop::current()->RunAllPending();
88     PlatformTest::TearDown();
89   }
90 
91  protected:
92   void KeepAliveConnectionResendRequestTest(const MockRead& read_failure);
93 
94   struct SimpleGetHelperResult {
95     int rv;
96     std::string status_line;
97     std::string response_data;
98   };
99 
SimpleGetHelper(MockRead data_reads[])100   SimpleGetHelperResult SimpleGetHelper(MockRead data_reads[]) {
101     SimpleGetHelperResult out;
102 
103     SessionDependencies session_deps;
104     scoped_ptr<HttpTransaction> trans(
105         new HttpNetworkTransaction(CreateSession(&session_deps)));
106 
107     HttpRequestInfo request;
108     request.method = "GET";
109     request.url = GURL("http://www.google.com/");
110     request.load_flags = 0;
111 
112     StaticSocketDataProvider data(data_reads, NULL);
113     session_deps.socket_factory.AddSocketDataProvider(&data);
114 
115     TestCompletionCallback callback;
116 
117     int rv = trans->Start(&request, &callback, NULL);
118     EXPECT_EQ(ERR_IO_PENDING, rv);
119 
120     out.rv = callback.WaitForResult();
121     if (out.rv != OK)
122       return out;
123 
124     const HttpResponseInfo* response = trans->GetResponseInfo();
125     EXPECT_TRUE(response != NULL);
126 
127     EXPECT_TRUE(response->headers != NULL);
128     out.status_line = response->headers->GetStatusLine();
129 
130     rv = ReadTransaction(trans.get(), &out.response_data);
131     EXPECT_EQ(OK, rv);
132 
133     return out;
134   }
135 
136   void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
137                                              int expected_status);
138 
139   void ConnectStatusHelper(const MockRead& status);
140 };
141 
142 // Fill |str| with a long header list that consumes >= |size| bytes.
FillLargeHeadersString(std::string * str,int size)143 void FillLargeHeadersString(std::string* str, int size) {
144   const char* row =
145       "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
146   const int sizeof_row = strlen(row);
147   const int num_rows = static_cast<int>(
148       ceil(static_cast<float>(size) / sizeof_row));
149   const int sizeof_data = num_rows * sizeof_row;
150   DCHECK(sizeof_data >= size);
151   str->reserve(sizeof_data);
152 
153   for (int i = 0; i < num_rows; ++i)
154     str->append(row, sizeof_row);
155 }
156 
157 // Alternative functions that eliminate randomness and dependency on the local
158 // host name so that the generated NTLM messages are reproducible.
MockGenerateRandom1(uint8 * output,size_t n)159 void MockGenerateRandom1(uint8* output, size_t n) {
160   static const uint8 bytes[] = {
161     0x55, 0x29, 0x66, 0x26, 0x6b, 0x9c, 0x73, 0x54
162   };
163   static size_t current_byte = 0;
164   for (size_t i = 0; i < n; ++i) {
165     output[i] = bytes[current_byte++];
166     current_byte %= arraysize(bytes);
167   }
168 }
169 
MockGenerateRandom2(uint8 * output,size_t n)170 void MockGenerateRandom2(uint8* output, size_t n) {
171   static const uint8 bytes[] = {
172     0x96, 0x79, 0x85, 0xe7, 0x49, 0x93, 0x70, 0xa1,
173     0x4e, 0xe7, 0x87, 0x45, 0x31, 0x5b, 0xd3, 0x1f
174   };
175   static size_t current_byte = 0;
176   for (size_t i = 0; i < n; ++i) {
177     output[i] = bytes[current_byte++];
178     current_byte %= arraysize(bytes);
179   }
180 }
181 
MockGetHostName()182 std::string MockGetHostName() {
183   return "WTC-WIN7";
184 }
185 
186 class CaptureGroupNameSocketPool : public TCPClientSocketPool {
187  public:
CaptureGroupNameSocketPool()188   CaptureGroupNameSocketPool() : TCPClientSocketPool(0, 0, NULL, NULL, NULL) {}
last_group_name_received() const189   const std::string last_group_name_received() const {
190     return last_group_name_;
191   }
192 
RequestSocket(const std::string & group_name,const void * socket_params,RequestPriority priority,ClientSocketHandle * handle,CompletionCallback * callback,LoadLog * load_log)193   virtual int RequestSocket(const std::string& group_name,
194                             const void* socket_params,
195                             RequestPriority priority,
196                             ClientSocketHandle* handle,
197                             CompletionCallback* callback,
198                             LoadLog* load_log) {
199     last_group_name_ = group_name;
200     return ERR_IO_PENDING;
201   }
CancelRequest(const std::string & group_name,const ClientSocketHandle * handle)202   virtual void CancelRequest(const std::string& group_name,
203                              const ClientSocketHandle* handle) { }
ReleaseSocket(const std::string & group_name,ClientSocket * socket)204   virtual void ReleaseSocket(const std::string& group_name,
205                              ClientSocket* socket) {}
CloseIdleSockets()206   virtual void CloseIdleSockets() {}
GetHostResolver() const207   virtual HostResolver* GetHostResolver() const {
208     return NULL;
209   }
IdleSocketCount() const210   virtual int IdleSocketCount() const {
211     return 0;
212   }
IdleSocketCountInGroup(const std::string & group_name) const213   virtual int IdleSocketCountInGroup(const std::string& group_name) const {
214     return 0;
215   }
GetLoadState(const std::string & group_name,const ClientSocketHandle * handle) const216   virtual LoadState GetLoadState(const std::string& group_name,
217                                  const ClientSocketHandle* handle) const {
218     return LOAD_STATE_IDLE;
219   }
220 
221  private:
222   std::string last_group_name_;
223 };
224 
225 //-----------------------------------------------------------------------------
226 
TEST_F(HttpNetworkTransactionTest,Basic)227 TEST_F(HttpNetworkTransactionTest, Basic) {
228   SessionDependencies session_deps;
229   scoped_ptr<HttpTransaction> trans(
230       new HttpNetworkTransaction(CreateSession(&session_deps)));
231 }
232 
TEST_F(HttpNetworkTransactionTest,SimpleGET)233 TEST_F(HttpNetworkTransactionTest, SimpleGET) {
234   MockRead data_reads[] = {
235     MockRead("HTTP/1.0 200 OK\r\n\r\n"),
236     MockRead("hello world"),
237     MockRead(false, OK),
238   };
239   SimpleGetHelperResult out = SimpleGetHelper(data_reads);
240   EXPECT_EQ(OK, out.rv);
241   EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
242   EXPECT_EQ("hello world", out.response_data);
243 }
244 
245 // Response with no status line.
TEST_F(HttpNetworkTransactionTest,SimpleGETNoHeaders)246 TEST_F(HttpNetworkTransactionTest, SimpleGETNoHeaders) {
247   MockRead data_reads[] = {
248     MockRead("hello world"),
249     MockRead(false, OK),
250   };
251   SimpleGetHelperResult out = SimpleGetHelper(data_reads);
252   EXPECT_EQ(OK, out.rv);
253   EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
254   EXPECT_EQ("hello world", out.response_data);
255 }
256 
257 // Allow up to 4 bytes of junk to precede status line.
TEST_F(HttpNetworkTransactionTest,StatusLineJunk2Bytes)258 TEST_F(HttpNetworkTransactionTest, StatusLineJunk2Bytes) {
259   MockRead data_reads[] = {
260     MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
261     MockRead(false, OK),
262   };
263   SimpleGetHelperResult out = SimpleGetHelper(data_reads);
264   EXPECT_EQ(OK, out.rv);
265   EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
266   EXPECT_EQ("DATA", out.response_data);
267 }
268 
269 // Allow up to 4 bytes of junk to precede status line.
TEST_F(HttpNetworkTransactionTest,StatusLineJunk4Bytes)270 TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes) {
271   MockRead data_reads[] = {
272     MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
273     MockRead(false, OK),
274   };
275   SimpleGetHelperResult out = SimpleGetHelper(data_reads);
276   EXPECT_EQ(OK, out.rv);
277   EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
278   EXPECT_EQ("DATA", out.response_data);
279 }
280 
281 // Beyond 4 bytes of slop and it should fail to find a status line.
TEST_F(HttpNetworkTransactionTest,StatusLineJunk5Bytes)282 TEST_F(HttpNetworkTransactionTest, StatusLineJunk5Bytes) {
283   MockRead data_reads[] = {
284     MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
285     MockRead(false, OK),
286   };
287   SimpleGetHelperResult out = SimpleGetHelper(data_reads);
288   EXPECT_EQ(OK, out.rv);
289   EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
290   EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data);
291 }
292 
293 // Same as StatusLineJunk4Bytes, except the read chunks are smaller.
TEST_F(HttpNetworkTransactionTest,StatusLineJunk4Bytes_Slow)294 TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) {
295   MockRead data_reads[] = {
296     MockRead("\n"),
297     MockRead("\n"),
298     MockRead("Q"),
299     MockRead("J"),
300     MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
301     MockRead(false, OK),
302   };
303   SimpleGetHelperResult out = SimpleGetHelper(data_reads);
304   EXPECT_EQ(OK, out.rv);
305   EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
306   EXPECT_EQ("DATA", out.response_data);
307 }
308 
309 // Close the connection before enough bytes to have a status line.
TEST_F(HttpNetworkTransactionTest,StatusLinePartial)310 TEST_F(HttpNetworkTransactionTest, StatusLinePartial) {
311   MockRead data_reads[] = {
312     MockRead("HTT"),
313     MockRead(false, OK),
314   };
315   SimpleGetHelperResult out = SimpleGetHelper(data_reads);
316   EXPECT_EQ(OK, out.rv);
317   EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
318   EXPECT_EQ("HTT", out.response_data);
319 }
320 
321 // Simulate a 204 response, lacking a Content-Length header, sent over a
322 // persistent connection.  The response should still terminate since a 204
323 // cannot have a response body.
TEST_F(HttpNetworkTransactionTest,StopsReading204)324 TEST_F(HttpNetworkTransactionTest, StopsReading204) {
325   MockRead data_reads[] = {
326     MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
327     MockRead("junk"),  // Should not be read!!
328     MockRead(false, OK),
329   };
330   SimpleGetHelperResult out = SimpleGetHelper(data_reads);
331   EXPECT_EQ(OK, out.rv);
332   EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line);
333   EXPECT_EQ("", out.response_data);
334 }
335 
336 // A simple request using chunked encoding with some extra data after.
337 // (Like might be seen in a pipelined response.)
TEST_F(HttpNetworkTransactionTest,ChunkedEncoding)338 TEST_F(HttpNetworkTransactionTest, ChunkedEncoding) {
339   MockRead data_reads[] = {
340     MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
341     MockRead("5\r\nHello\r\n"),
342     MockRead("1\r\n"),
343     MockRead(" \r\n"),
344     MockRead("5\r\nworld\r\n"),
345     MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
346     MockRead(false, OK),
347   };
348   SimpleGetHelperResult out = SimpleGetHelper(data_reads);
349   EXPECT_EQ(OK, out.rv);
350   EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
351   EXPECT_EQ("Hello world", out.response_data);
352 }
353 
354 // Do a request using the HEAD method. Verify that we don't try to read the
355 // message body (since HEAD has none).
TEST_F(HttpNetworkTransactionTest,Head)356 TEST_F(HttpNetworkTransactionTest, Head) {
357   SessionDependencies session_deps;
358   scoped_ptr<HttpTransaction> trans(
359       new HttpNetworkTransaction(CreateSession(&session_deps)));
360 
361   HttpRequestInfo request;
362   request.method = "HEAD";
363   request.url = GURL("http://www.google.com/");
364   request.load_flags = 0;
365 
366   MockWrite data_writes1[] = {
367     MockWrite("HEAD / HTTP/1.1\r\n"
368               "Host: www.google.com\r\n"
369               "Connection: keep-alive\r\n"
370               "Content-Length: 0\r\n\r\n"),
371   };
372   MockRead data_reads1[] = {
373     MockRead("HTTP/1.1 404 Not Found\r\n"),
374     MockRead("Server: Blah\r\n"),
375     MockRead("Content-Length: 1234\r\n\r\n"),
376 
377     // No response body because the test stops reading here.
378     MockRead(false, ERR_UNEXPECTED),  // Should not be reached.
379   };
380 
381   StaticSocketDataProvider data1(data_reads1, data_writes1);
382   session_deps.socket_factory.AddSocketDataProvider(&data1);
383 
384   TestCompletionCallback callback1;
385 
386   int rv = trans->Start(&request, &callback1, NULL);
387   EXPECT_EQ(ERR_IO_PENDING, rv);
388 
389   rv = callback1.WaitForResult();
390   EXPECT_EQ(OK, rv);
391 
392   const HttpResponseInfo* response = trans->GetResponseInfo();
393   EXPECT_FALSE(response == NULL);
394 
395   // Check that the headers got parsed.
396   EXPECT_TRUE(response->headers != NULL);
397   EXPECT_EQ(1234, response->headers->GetContentLength());
398   EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine());
399 
400   std::string server_header;
401   void* iter = NULL;
402   bool has_server_header = response->headers->EnumerateHeader(
403       &iter, "Server", &server_header);
404   EXPECT_TRUE(has_server_header);
405   EXPECT_EQ("Blah", server_header);
406 
407   // Reading should give EOF right away, since there is no message body
408   // (despite non-zero content-length).
409   std::string response_data;
410   rv = ReadTransaction(trans.get(), &response_data);
411   EXPECT_EQ(OK, rv);
412   EXPECT_EQ("", response_data);
413 }
414 
TEST_F(HttpNetworkTransactionTest,ReuseConnection)415 TEST_F(HttpNetworkTransactionTest, ReuseConnection) {
416   SessionDependencies session_deps;
417   scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
418 
419   MockRead data_reads[] = {
420     MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
421     MockRead("hello"),
422     MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
423     MockRead("world"),
424     MockRead(false, OK),
425   };
426   StaticSocketDataProvider data(data_reads, NULL);
427   session_deps.socket_factory.AddSocketDataProvider(&data);
428 
429   const char* kExpectedResponseData[] = {
430     "hello", "world"
431   };
432 
433   for (int i = 0; i < 2; ++i) {
434     scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
435 
436     HttpRequestInfo request;
437     request.method = "GET";
438     request.url = GURL("http://www.google.com/");
439     request.load_flags = 0;
440 
441     TestCompletionCallback callback;
442 
443     int rv = trans->Start(&request, &callback, NULL);
444     EXPECT_EQ(ERR_IO_PENDING, rv);
445 
446     rv = callback.WaitForResult();
447     EXPECT_EQ(OK, rv);
448 
449     const HttpResponseInfo* response = trans->GetResponseInfo();
450     EXPECT_TRUE(response != NULL);
451 
452     EXPECT_TRUE(response->headers != NULL);
453     EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
454 
455     std::string response_data;
456     rv = ReadTransaction(trans.get(), &response_data);
457     EXPECT_EQ(OK, rv);
458     EXPECT_EQ(kExpectedResponseData[i], response_data);
459   }
460 }
461 
TEST_F(HttpNetworkTransactionTest,Ignores100)462 TEST_F(HttpNetworkTransactionTest, Ignores100) {
463   SessionDependencies session_deps;
464   scoped_ptr<HttpTransaction> trans(
465       new HttpNetworkTransaction(CreateSession(&session_deps)));
466 
467   HttpRequestInfo request;
468   request.method = "POST";
469   request.url = GURL("http://www.foo.com/");
470   request.upload_data = new UploadData;
471   request.upload_data->AppendBytes("foo", 3);
472   request.load_flags = 0;
473 
474   MockRead data_reads[] = {
475     MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
476     MockRead("HTTP/1.0 200 OK\r\n\r\n"),
477     MockRead("hello world"),
478     MockRead(false, OK),
479   };
480   StaticSocketDataProvider data(data_reads, NULL);
481   session_deps.socket_factory.AddSocketDataProvider(&data);
482 
483   TestCompletionCallback callback;
484 
485   int rv = trans->Start(&request, &callback, NULL);
486   EXPECT_EQ(ERR_IO_PENDING, rv);
487 
488   rv = callback.WaitForResult();
489   EXPECT_EQ(OK, rv);
490 
491   const HttpResponseInfo* response = trans->GetResponseInfo();
492   EXPECT_TRUE(response != NULL);
493 
494   EXPECT_TRUE(response->headers != NULL);
495   EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
496 
497   std::string response_data;
498   rv = ReadTransaction(trans.get(), &response_data);
499   EXPECT_EQ(OK, rv);
500   EXPECT_EQ("hello world", response_data);
501 }
502 
503 // This test is almost the same as Ignores100 above, but the response contains
504 // a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
505 // HTTP/1.1 and the two status headers are read in one read.
TEST_F(HttpNetworkTransactionTest,Ignores1xx)506 TEST_F(HttpNetworkTransactionTest, Ignores1xx) {
507   SessionDependencies session_deps;
508   scoped_ptr<HttpTransaction> trans(
509       new HttpNetworkTransaction(CreateSession(&session_deps)));
510 
511   HttpRequestInfo request;
512   request.method = "GET";
513   request.url = GURL("http://www.foo.com/");
514   request.load_flags = 0;
515 
516   MockRead data_reads[] = {
517     MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
518              "HTTP/1.1 200 OK\r\n\r\n"),
519     MockRead("hello world"),
520     MockRead(false, OK),
521   };
522   StaticSocketDataProvider data(data_reads, NULL);
523   session_deps.socket_factory.AddSocketDataProvider(&data);
524 
525   TestCompletionCallback callback;
526 
527   int rv = trans->Start(&request, &callback, NULL);
528   EXPECT_EQ(ERR_IO_PENDING, rv);
529 
530   rv = callback.WaitForResult();
531   EXPECT_EQ(OK, rv);
532 
533   const HttpResponseInfo* response = trans->GetResponseInfo();
534   EXPECT_TRUE(response != NULL);
535 
536   EXPECT_TRUE(response->headers != NULL);
537   EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
538 
539   std::string response_data;
540   rv = ReadTransaction(trans.get(), &response_data);
541   EXPECT_EQ(OK, rv);
542   EXPECT_EQ("hello world", response_data);
543 }
544 
TEST_F(HttpNetworkTransactionTest,Incomplete100ThenEOF)545 TEST_F(HttpNetworkTransactionTest, Incomplete100ThenEOF) {
546   SessionDependencies session_deps;
547   scoped_ptr<HttpTransaction> trans(
548       new HttpNetworkTransaction(CreateSession(&session_deps)));
549 
550   HttpRequestInfo request;
551   request.method = "POST";
552   request.url = GURL("http://www.foo.com/");
553   request.load_flags = 0;
554 
555   MockRead data_reads[] = {
556     MockRead(false, "HTTP/1.0 100 Continue\r\n"),
557     MockRead(true, 0),
558   };
559   StaticSocketDataProvider data(data_reads, NULL);
560   session_deps.socket_factory.AddSocketDataProvider(&data);
561 
562   TestCompletionCallback callback;
563 
564   int rv = trans->Start(&request, &callback, NULL);
565   EXPECT_EQ(ERR_IO_PENDING, rv);
566 
567   rv = callback.WaitForResult();
568   EXPECT_EQ(OK, rv);
569 
570   std::string response_data;
571   rv = ReadTransaction(trans.get(), &response_data);
572   EXPECT_EQ(OK, rv);
573   EXPECT_EQ("", response_data);
574 }
575 
TEST_F(HttpNetworkTransactionTest,EmptyResponse)576 TEST_F(HttpNetworkTransactionTest, EmptyResponse) {
577   SessionDependencies session_deps;
578   scoped_ptr<HttpTransaction> trans(
579       new HttpNetworkTransaction(CreateSession(&session_deps)));
580 
581   HttpRequestInfo request;
582   request.method = "POST";
583   request.url = GURL("http://www.foo.com/");
584   request.load_flags = 0;
585 
586   MockRead data_reads[] = {
587     MockRead(true, 0),
588   };
589   StaticSocketDataProvider data(data_reads, NULL);
590   session_deps.socket_factory.AddSocketDataProvider(&data);
591 
592   TestCompletionCallback callback;
593 
594   int rv = trans->Start(&request, &callback, NULL);
595   EXPECT_EQ(ERR_IO_PENDING, rv);
596 
597   rv = callback.WaitForResult();
598   EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
599 }
600 
601 // read_failure specifies a read failure that should cause the network
602 // transaction to resend the request.
KeepAliveConnectionResendRequestTest(const MockRead & read_failure)603 void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
604     const MockRead& read_failure) {
605   SessionDependencies session_deps;
606   scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
607 
608   HttpRequestInfo request;
609   request.method = "GET";
610   request.url = GURL("http://www.foo.com/");
611   request.load_flags = 0;
612 
613   MockRead data1_reads[] = {
614     MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
615     MockRead("hello"),
616     read_failure,  // Now, we reuse the connection and fail the first read.
617   };
618   StaticSocketDataProvider data1(data1_reads, NULL);
619   session_deps.socket_factory.AddSocketDataProvider(&data1);
620 
621   MockRead data2_reads[] = {
622     MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
623     MockRead("world"),
624     MockRead(true, OK),
625   };
626   StaticSocketDataProvider data2(data2_reads, NULL);
627   session_deps.socket_factory.AddSocketDataProvider(&data2);
628 
629   const char* kExpectedResponseData[] = {
630     "hello", "world"
631   };
632 
633   for (int i = 0; i < 2; ++i) {
634     TestCompletionCallback callback;
635 
636     scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
637 
638     int rv = trans->Start(&request, &callback, NULL);
639     EXPECT_EQ(ERR_IO_PENDING, rv);
640 
641     rv = callback.WaitForResult();
642     EXPECT_EQ(OK, rv);
643 
644     const HttpResponseInfo* response = trans->GetResponseInfo();
645     EXPECT_TRUE(response != NULL);
646 
647     EXPECT_TRUE(response->headers != NULL);
648     EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
649 
650     std::string response_data;
651     rv = ReadTransaction(trans.get(), &response_data);
652     EXPECT_EQ(OK, rv);
653     EXPECT_EQ(kExpectedResponseData[i], response_data);
654   }
655 }
656 
TEST_F(HttpNetworkTransactionTest,KeepAliveConnectionReset)657 TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
658   MockRead read_failure(true, ERR_CONNECTION_RESET);
659   KeepAliveConnectionResendRequestTest(read_failure);
660 }
661 
TEST_F(HttpNetworkTransactionTest,KeepAliveConnectionEOF)662 TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
663   MockRead read_failure(false, OK);  // EOF
664   KeepAliveConnectionResendRequestTest(read_failure);
665 }
666 
TEST_F(HttpNetworkTransactionTest,NonKeepAliveConnectionReset)667 TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
668   SessionDependencies session_deps;
669   scoped_ptr<HttpTransaction> trans(
670       new HttpNetworkTransaction(CreateSession(&session_deps)));
671 
672   HttpRequestInfo request;
673   request.method = "GET";
674   request.url = GURL("http://www.google.com/");
675   request.load_flags = 0;
676 
677   MockRead data_reads[] = {
678     MockRead(true, ERR_CONNECTION_RESET),
679     MockRead("HTTP/1.0 200 OK\r\n\r\n"),  // Should not be used
680     MockRead("hello world"),
681     MockRead(false, OK),
682   };
683   StaticSocketDataProvider data(data_reads, NULL);
684   session_deps.socket_factory.AddSocketDataProvider(&data);
685 
686   TestCompletionCallback callback;
687 
688   int rv = trans->Start(&request, &callback, NULL);
689   EXPECT_EQ(ERR_IO_PENDING, rv);
690 
691   rv = callback.WaitForResult();
692   EXPECT_EQ(ERR_CONNECTION_RESET, rv);
693 
694   const HttpResponseInfo* response = trans->GetResponseInfo();
695   EXPECT_TRUE(response == NULL);
696 }
697 
698 // What do various browsers do when the server closes a non-keepalive
699 // connection without sending any response header or body?
700 //
701 // IE7: error page
702 // Safari 3.1.2 (Windows): error page
703 // Firefox 3.0.1: blank page
704 // Opera 9.52: after five attempts, blank page
705 // Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
706 // Us: error page (EMPTY_RESPONSE)
TEST_F(HttpNetworkTransactionTest,NonKeepAliveConnectionEOF)707 TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
708   MockRead data_reads[] = {
709     MockRead(false, OK),  // EOF
710     MockRead("HTTP/1.0 200 OK\r\n\r\n"),  // Should not be used
711     MockRead("hello world"),
712     MockRead(false, OK),
713   };
714   SimpleGetHelperResult out = SimpleGetHelper(data_reads);
715   EXPECT_EQ(ERR_EMPTY_RESPONSE, out.rv);
716 }
717 
718 // Test the request-challenge-retry sequence for basic auth.
719 // (basic auth is the easiest to mock, because it has no randomness).
TEST_F(HttpNetworkTransactionTest,BasicAuth)720 TEST_F(HttpNetworkTransactionTest, BasicAuth) {
721   SessionDependencies session_deps;
722   scoped_ptr<HttpTransaction> trans(
723       new HttpNetworkTransaction(CreateSession(&session_deps)));
724 
725   HttpRequestInfo request;
726   request.method = "GET";
727   request.url = GURL("http://www.google.com/");
728   request.load_flags = 0;
729 
730   MockWrite data_writes1[] = {
731     MockWrite("GET / HTTP/1.1\r\n"
732               "Host: www.google.com\r\n"
733               "Connection: keep-alive\r\n\r\n"),
734   };
735 
736   MockRead data_reads1[] = {
737     MockRead("HTTP/1.0 401 Unauthorized\r\n"),
738     // Give a couple authenticate options (only the middle one is actually
739     // supported).
740     MockRead("WWW-Authenticate: Basic invalid\r\n"),  // Malformed.
741     MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
742     MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
743     MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
744     // Large content-length -- won't matter, as connection will be reset.
745     MockRead("Content-Length: 10000\r\n\r\n"),
746     MockRead(false, ERR_FAILED),
747   };
748 
749   // After calling trans->RestartWithAuth(), this is the request we should
750   // be issuing -- the final header line contains the credentials.
751   MockWrite data_writes2[] = {
752     MockWrite("GET / HTTP/1.1\r\n"
753               "Host: www.google.com\r\n"
754               "Connection: keep-alive\r\n"
755               "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
756   };
757 
758   // Lastly, the server responds with the actual content.
759   MockRead data_reads2[] = {
760     MockRead("HTTP/1.0 200 OK\r\n"),
761     MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
762     MockRead("Content-Length: 100\r\n\r\n"),
763     MockRead(false, OK),
764   };
765 
766   StaticSocketDataProvider data1(data_reads1, data_writes1);
767   StaticSocketDataProvider data2(data_reads2, data_writes2);
768   session_deps.socket_factory.AddSocketDataProvider(&data1);
769   session_deps.socket_factory.AddSocketDataProvider(&data2);
770 
771   TestCompletionCallback callback1;
772 
773   int rv = trans->Start(&request, &callback1, NULL);
774   EXPECT_EQ(ERR_IO_PENDING, rv);
775 
776   rv = callback1.WaitForResult();
777   EXPECT_EQ(OK, rv);
778 
779   const HttpResponseInfo* response = trans->GetResponseInfo();
780   EXPECT_FALSE(response == NULL);
781 
782   // The password prompt info should have been set in response->auth_challenge.
783   EXPECT_FALSE(response->auth_challenge.get() == NULL);
784 
785   EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
786   EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
787   EXPECT_EQ(L"basic", response->auth_challenge->scheme);
788 
789   TestCompletionCallback callback2;
790 
791   rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
792   EXPECT_EQ(ERR_IO_PENDING, rv);
793 
794   rv = callback2.WaitForResult();
795   EXPECT_EQ(OK, rv);
796 
797   response = trans->GetResponseInfo();
798   EXPECT_FALSE(response == NULL);
799   EXPECT_TRUE(response->auth_challenge.get() == NULL);
800   EXPECT_EQ(100, response->headers->GetContentLength());
801 }
802 
TEST_F(HttpNetworkTransactionTest,DoNotSendAuth)803 TEST_F(HttpNetworkTransactionTest, DoNotSendAuth) {
804   SessionDependencies session_deps;
805   scoped_ptr<HttpTransaction> trans(
806       new HttpNetworkTransaction(CreateSession(&session_deps)));
807 
808   HttpRequestInfo request;
809   request.method = "GET";
810   request.url = GURL("http://www.google.com/");
811   request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
812 
813   MockWrite data_writes[] = {
814     MockWrite("GET / HTTP/1.1\r\n"
815               "Host: www.google.com\r\n"
816               "Connection: keep-alive\r\n\r\n"),
817   };
818 
819   MockRead data_reads[] = {
820     MockRead("HTTP/1.0 401 Unauthorized\r\n"),
821     MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
822     MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
823     // Large content-length -- won't matter, as connection will be reset.
824     MockRead("Content-Length: 10000\r\n\r\n"),
825     MockRead(false, ERR_FAILED),
826   };
827 
828   StaticSocketDataProvider data(data_reads, data_writes);
829   session_deps.socket_factory.AddSocketDataProvider(&data);
830   TestCompletionCallback callback;
831 
832   int rv = trans->Start(&request, &callback, NULL);
833   EXPECT_EQ(ERR_IO_PENDING, rv);
834 
835   rv = callback.WaitForResult();
836   EXPECT_EQ(0, rv);
837 
838   const HttpResponseInfo* response = trans->GetResponseInfo();
839   ASSERT_FALSE(response == NULL);
840   EXPECT_TRUE(response->auth_challenge.get() == NULL);
841 }
842 
843 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
844 // connection.
TEST_F(HttpNetworkTransactionTest,BasicAuthKeepAlive)845 TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
846   SessionDependencies session_deps;
847   scoped_ptr<HttpTransaction> trans(
848       new HttpNetworkTransaction(CreateSession(&session_deps)));
849 
850   HttpRequestInfo request;
851   request.method = "GET";
852   request.url = GURL("http://www.google.com/");
853   request.load_flags = 0;
854 
855   MockWrite data_writes1[] = {
856     MockWrite("GET / HTTP/1.1\r\n"
857               "Host: www.google.com\r\n"
858               "Connection: keep-alive\r\n\r\n"),
859 
860     // After calling trans->RestartWithAuth(), this is the request we should
861     // be issuing -- the final header line contains the credentials.
862     MockWrite("GET / HTTP/1.1\r\n"
863               "Host: www.google.com\r\n"
864               "Connection: keep-alive\r\n"
865               "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
866   };
867 
868   MockRead data_reads1[] = {
869     MockRead("HTTP/1.1 401 Unauthorized\r\n"),
870     MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
871     MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
872     MockRead("Content-Length: 14\r\n\r\n"),
873     MockRead("Unauthorized\r\n"),
874 
875     // Lastly, the server responds with the actual content.
876     MockRead("HTTP/1.1 200 OK\r\n"),
877     MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
878     MockRead("Content-Length: 100\r\n\r\n"),
879     MockRead(false, OK),
880   };
881 
882   StaticSocketDataProvider data1(data_reads1, data_writes1);
883   session_deps.socket_factory.AddSocketDataProvider(&data1);
884 
885   TestCompletionCallback callback1;
886 
887   int rv = trans->Start(&request, &callback1, NULL);
888   EXPECT_EQ(ERR_IO_PENDING, rv);
889 
890   rv = callback1.WaitForResult();
891   EXPECT_EQ(OK, rv);
892 
893   const HttpResponseInfo* response = trans->GetResponseInfo();
894   EXPECT_FALSE(response == NULL);
895 
896   // The password prompt info should have been set in response->auth_challenge.
897   EXPECT_FALSE(response->auth_challenge.get() == NULL);
898 
899   EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
900   EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
901   EXPECT_EQ(L"basic", response->auth_challenge->scheme);
902 
903   TestCompletionCallback callback2;
904 
905   rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
906   EXPECT_EQ(ERR_IO_PENDING, rv);
907 
908   rv = callback2.WaitForResult();
909   EXPECT_EQ(OK, rv);
910 
911   response = trans->GetResponseInfo();
912   EXPECT_FALSE(response == NULL);
913   EXPECT_TRUE(response->auth_challenge.get() == NULL);
914   EXPECT_EQ(100, response->headers->GetContentLength());
915 }
916 
917 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
918 // connection and with no response body to drain.
TEST_F(HttpNetworkTransactionTest,BasicAuthKeepAliveNoBody)919 TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
920   SessionDependencies session_deps;
921   scoped_ptr<HttpTransaction> trans(
922       new HttpNetworkTransaction(CreateSession(&session_deps)));
923 
924   HttpRequestInfo request;
925   request.method = "GET";
926   request.url = GURL("http://www.google.com/");
927   request.load_flags = 0;
928 
929   MockWrite data_writes1[] = {
930     MockWrite("GET / HTTP/1.1\r\n"
931               "Host: www.google.com\r\n"
932               "Connection: keep-alive\r\n\r\n"),
933 
934     // After calling trans->RestartWithAuth(), this is the request we should
935     // be issuing -- the final header line contains the credentials.
936     MockWrite("GET / HTTP/1.1\r\n"
937               "Host: www.google.com\r\n"
938               "Connection: keep-alive\r\n"
939               "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
940   };
941 
942   MockRead data_reads1[] = {
943     MockRead("HTTP/1.1 401 Unauthorized\r\n"),
944     MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
945     MockRead("Content-Length: 0\r\n\r\n"),  // No response body.
946 
947     // Lastly, the server responds with the actual content.
948     MockRead("HTTP/1.1 200 OK\r\n"),
949     MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
950     MockRead("Content-Length: 100\r\n\r\n"),
951     MockRead(false, OK),
952   };
953 
954   StaticSocketDataProvider data1(data_reads1, data_writes1);
955   session_deps.socket_factory.AddSocketDataProvider(&data1);
956 
957   TestCompletionCallback callback1;
958 
959   int rv = trans->Start(&request, &callback1, NULL);
960   EXPECT_EQ(ERR_IO_PENDING, rv);
961 
962   rv = callback1.WaitForResult();
963   EXPECT_EQ(OK, rv);
964 
965   const HttpResponseInfo* response = trans->GetResponseInfo();
966   EXPECT_FALSE(response == NULL);
967 
968   // The password prompt info should have been set in response->auth_challenge.
969   EXPECT_FALSE(response->auth_challenge.get() == NULL);
970 
971   EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
972   EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
973   EXPECT_EQ(L"basic", response->auth_challenge->scheme);
974 
975   TestCompletionCallback callback2;
976 
977   rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
978   EXPECT_EQ(ERR_IO_PENDING, rv);
979 
980   rv = callback2.WaitForResult();
981   EXPECT_EQ(OK, rv);
982 
983   response = trans->GetResponseInfo();
984   EXPECT_FALSE(response == NULL);
985   EXPECT_TRUE(response->auth_challenge.get() == NULL);
986   EXPECT_EQ(100, response->headers->GetContentLength());
987 }
988 
989 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
990 // connection and with a large response body to drain.
TEST_F(HttpNetworkTransactionTest,BasicAuthKeepAliveLargeBody)991 TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
992   SessionDependencies session_deps;
993   scoped_ptr<HttpTransaction> trans(
994       new HttpNetworkTransaction(CreateSession(&session_deps)));
995 
996   HttpRequestInfo request;
997   request.method = "GET";
998   request.url = GURL("http://www.google.com/");
999   request.load_flags = 0;
1000 
1001   MockWrite data_writes1[] = {
1002     MockWrite("GET / HTTP/1.1\r\n"
1003               "Host: www.google.com\r\n"
1004               "Connection: keep-alive\r\n\r\n"),
1005 
1006     // After calling trans->RestartWithAuth(), this is the request we should
1007     // be issuing -- the final header line contains the credentials.
1008     MockWrite("GET / HTTP/1.1\r\n"
1009               "Host: www.google.com\r\n"
1010               "Connection: keep-alive\r\n"
1011               "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1012   };
1013 
1014   // Respond with 5 kb of response body.
1015   std::string large_body_string("Unauthorized");
1016   large_body_string.append(5 * 1024, ' ');
1017   large_body_string.append("\r\n");
1018 
1019   MockRead data_reads1[] = {
1020     MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1021     MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1022     MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1023     // 5134 = 12 + 5 * 1024 + 2
1024     MockRead("Content-Length: 5134\r\n\r\n"),
1025     MockRead(true, large_body_string.data(), large_body_string.size()),
1026 
1027     // Lastly, the server responds with the actual content.
1028     MockRead("HTTP/1.1 200 OK\r\n"),
1029     MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1030     MockRead("Content-Length: 100\r\n\r\n"),
1031     MockRead(false, OK),
1032   };
1033 
1034   StaticSocketDataProvider data1(data_reads1, data_writes1);
1035   session_deps.socket_factory.AddSocketDataProvider(&data1);
1036 
1037   TestCompletionCallback callback1;
1038 
1039   int rv = trans->Start(&request, &callback1, NULL);
1040   EXPECT_EQ(ERR_IO_PENDING, rv);
1041 
1042   rv = callback1.WaitForResult();
1043   EXPECT_EQ(OK, rv);
1044 
1045   const HttpResponseInfo* response = trans->GetResponseInfo();
1046   EXPECT_FALSE(response == NULL);
1047 
1048   // The password prompt info should have been set in response->auth_challenge.
1049   EXPECT_FALSE(response->auth_challenge.get() == NULL);
1050 
1051   EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
1052   EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1053   EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1054 
1055   TestCompletionCallback callback2;
1056 
1057   rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
1058   EXPECT_EQ(ERR_IO_PENDING, rv);
1059 
1060   rv = callback2.WaitForResult();
1061   EXPECT_EQ(OK, rv);
1062 
1063   response = trans->GetResponseInfo();
1064   EXPECT_FALSE(response == NULL);
1065   EXPECT_TRUE(response->auth_challenge.get() == NULL);
1066   EXPECT_EQ(100, response->headers->GetContentLength());
1067 }
1068 
1069 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
1070 // connection, but the server gets impatient and closes the connection.
TEST_F(HttpNetworkTransactionTest,BasicAuthKeepAliveImpatientServer)1071 TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) {
1072   SessionDependencies session_deps;
1073   scoped_ptr<HttpTransaction> trans(
1074       new HttpNetworkTransaction(CreateSession(&session_deps)));
1075 
1076   HttpRequestInfo request;
1077   request.method = "GET";
1078   request.url = GURL("http://www.google.com/");
1079   request.load_flags = 0;
1080 
1081   MockWrite data_writes1[] = {
1082     MockWrite("GET / HTTP/1.1\r\n"
1083               "Host: www.google.com\r\n"
1084               "Connection: keep-alive\r\n\r\n"),
1085     // This simulates the seemingly successful write to a closed connection
1086     // if the bug is not fixed.
1087     MockWrite("GET / HTTP/1.1\r\n"
1088               "Host: www.google.com\r\n"
1089               "Connection: keep-alive\r\n"
1090               "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1091   };
1092 
1093   MockRead data_reads1[] = {
1094     MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1095     MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1096     MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1097     MockRead("Content-Length: 14\r\n\r\n"),
1098     // Tell MockTCPClientSocket to simulate the server closing the connection.
1099     MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
1100     MockRead("Unauthorized\r\n"),
1101     MockRead(false, OK),  // The server closes the connection.
1102   };
1103 
1104   // After calling trans->RestartWithAuth(), this is the request we should
1105   // be issuing -- the final header line contains the credentials.
1106   MockWrite data_writes2[] = {
1107     MockWrite("GET / HTTP/1.1\r\n"
1108               "Host: www.google.com\r\n"
1109               "Connection: keep-alive\r\n"
1110               "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1111   };
1112 
1113   // Lastly, the server responds with the actual content.
1114   MockRead data_reads2[] = {
1115     MockRead("HTTP/1.1 200 OK\r\n"),
1116     MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1117     MockRead("Content-Length: 100\r\n\r\n"),
1118     MockRead(false, OK),
1119   };
1120 
1121   StaticSocketDataProvider data1(data_reads1, data_writes1);
1122   StaticSocketDataProvider data2(data_reads2, data_writes2);
1123   session_deps.socket_factory.AddSocketDataProvider(&data1);
1124   session_deps.socket_factory.AddSocketDataProvider(&data2);
1125 
1126   TestCompletionCallback callback1;
1127 
1128   int rv = trans->Start(&request, &callback1, NULL);
1129   EXPECT_EQ(ERR_IO_PENDING, rv);
1130 
1131   rv = callback1.WaitForResult();
1132   EXPECT_EQ(OK, rv);
1133 
1134   const HttpResponseInfo* response = trans->GetResponseInfo();
1135   EXPECT_FALSE(response == NULL);
1136 
1137   // The password prompt info should have been set in response->auth_challenge.
1138   EXPECT_FALSE(response->auth_challenge.get() == NULL);
1139 
1140   EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
1141   EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1142   EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1143 
1144   TestCompletionCallback callback2;
1145 
1146   rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
1147   EXPECT_EQ(ERR_IO_PENDING, rv);
1148 
1149   rv = callback2.WaitForResult();
1150   EXPECT_EQ(OK, rv);
1151 
1152   response = trans->GetResponseInfo();
1153   ASSERT_FALSE(response == NULL);
1154   EXPECT_TRUE(response->auth_challenge.get() == NULL);
1155   EXPECT_EQ(100, response->headers->GetContentLength());
1156 }
1157 
1158 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
1159 // proxy connection, when setting up an SSL tunnel.
TEST_F(HttpNetworkTransactionTest,BasicAuthProxyKeepAlive)1160 TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAlive) {
1161   // Configure against proxy server "myproxy:70".
1162   SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
1163   scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1164 
1165   scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1166 
1167   HttpRequestInfo request;
1168   request.method = "GET";
1169   request.url = GURL("https://www.google.com/");
1170   // Ensure that proxy authentication is attempted even
1171   // when the no authentication data flag is set.
1172   request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
1173 
1174   // Since we have proxy, should try to establish tunnel.
1175   MockWrite data_writes1[] = {
1176     MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1177               "Host: www.google.com\r\n"
1178               "Proxy-Connection: keep-alive\r\n\r\n"),
1179 
1180     // After calling trans->RestartWithAuth(), this is the request we should
1181     // be issuing -- the final header line contains the credentials.
1182     MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1183               "Host: www.google.com\r\n"
1184               "Proxy-Connection: keep-alive\r\n"
1185               "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
1186   };
1187 
1188   // The proxy responds to the connect with a 407, using a persistent
1189   // connection.
1190   MockRead data_reads1[] = {
1191     // No credentials.
1192     MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1193     MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1194     MockRead("Content-Length: 10\r\n\r\n"),
1195     MockRead("0123456789"),
1196 
1197     // Wrong credentials (wrong password).
1198     MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1199     MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1200     MockRead("Content-Length: 10\r\n\r\n"),
1201     // No response body because the test stops reading here.
1202     MockRead(false, ERR_UNEXPECTED),  // Should not be reached.
1203   };
1204 
1205   StaticSocketDataProvider data1(data_reads1, data_writes1);
1206   session_deps.socket_factory.AddSocketDataProvider(&data1);
1207 
1208   TestCompletionCallback callback1;
1209 
1210   int rv = trans->Start(&request, &callback1, NULL);
1211   EXPECT_EQ(ERR_IO_PENDING, rv);
1212 
1213   rv = callback1.WaitForResult();
1214   EXPECT_EQ(OK, rv);
1215 
1216   const HttpResponseInfo* response = trans->GetResponseInfo();
1217   EXPECT_FALSE(response == NULL);
1218 
1219   EXPECT_TRUE(response->headers->IsKeepAlive());
1220   EXPECT_EQ(407, response->headers->response_code());
1221   EXPECT_EQ(10, response->headers->GetContentLength());
1222   EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
1223 
1224   // The password prompt info should have been set in response->auth_challenge.
1225   EXPECT_FALSE(response->auth_challenge.get() == NULL);
1226 
1227   EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
1228   EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1229   EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1230 
1231   TestCompletionCallback callback2;
1232 
1233   // Wrong password (should be "bar").
1234   rv = trans->RestartWithAuth(L"foo", L"baz", &callback2);
1235   EXPECT_EQ(ERR_IO_PENDING, rv);
1236 
1237   rv = callback2.WaitForResult();
1238   EXPECT_EQ(OK, rv);
1239 
1240   response = trans->GetResponseInfo();
1241   EXPECT_FALSE(response == NULL);
1242 
1243   EXPECT_TRUE(response->headers->IsKeepAlive());
1244   EXPECT_EQ(407, response->headers->response_code());
1245   EXPECT_EQ(10, response->headers->GetContentLength());
1246   EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
1247 
1248   // The password prompt info should have been set in response->auth_challenge.
1249   EXPECT_FALSE(response->auth_challenge.get() == NULL);
1250 
1251   EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
1252   EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1253   EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1254 }
1255 
1256 // Test that we don't read the response body when we fail to establish a tunnel,
1257 // even if the user cancels the proxy's auth attempt.
TEST_F(HttpNetworkTransactionTest,BasicAuthProxyCancelTunnel)1258 TEST_F(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
1259   // Configure against proxy server "myproxy:70".
1260   SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
1261 
1262   scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1263 
1264   scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1265 
1266   HttpRequestInfo request;
1267   request.method = "GET";
1268   request.url = GURL("https://www.google.com/");
1269   request.load_flags = 0;
1270 
1271   // Since we have proxy, should try to establish tunnel.
1272   MockWrite data_writes[] = {
1273     MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1274               "Host: www.google.com\r\n"
1275               "Proxy-Connection: keep-alive\r\n\r\n"),
1276   };
1277 
1278   // The proxy responds to the connect with a 407.
1279   MockRead data_reads[] = {
1280     MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1281     MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1282     MockRead("Content-Length: 10\r\n\r\n"),
1283     MockRead(false, ERR_UNEXPECTED),  // Should not be reached.
1284   };
1285 
1286   StaticSocketDataProvider data(data_reads, data_writes);
1287   session_deps.socket_factory.AddSocketDataProvider(&data);
1288 
1289   TestCompletionCallback callback;
1290 
1291   int rv = trans->Start(&request, &callback, NULL);
1292   EXPECT_EQ(ERR_IO_PENDING, rv);
1293 
1294   rv = callback.WaitForResult();
1295   EXPECT_EQ(OK, rv);
1296 
1297   const HttpResponseInfo* response = trans->GetResponseInfo();
1298   EXPECT_FALSE(response == NULL);
1299 
1300   EXPECT_TRUE(response->headers->IsKeepAlive());
1301   EXPECT_EQ(407, response->headers->response_code());
1302   EXPECT_EQ(10, response->headers->GetContentLength());
1303   EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
1304 
1305   std::string response_data;
1306   rv = ReadTransaction(trans.get(), &response_data);
1307   EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
1308 }
1309 
ConnectStatusHelperWithExpectedStatus(const MockRead & status,int expected_status)1310 void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
1311     const MockRead& status, int expected_status) {
1312   // Configure against proxy server "myproxy:70".
1313   SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
1314 
1315   scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1316 
1317   scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1318 
1319   HttpRequestInfo request;
1320   request.method = "GET";
1321   request.url = GURL("https://www.google.com/");
1322   request.load_flags = 0;
1323 
1324   // Since we have proxy, should try to establish tunnel.
1325   MockWrite data_writes[] = {
1326     MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1327               "Host: www.google.com\r\n"
1328               "Proxy-Connection: keep-alive\r\n\r\n"),
1329   };
1330 
1331   MockRead data_reads[] = {
1332     status,
1333     MockRead("Content-Length: 10\r\n\r\n"),
1334     // No response body because the test stops reading here.
1335     MockRead(false, ERR_UNEXPECTED),  // Should not be reached.
1336   };
1337 
1338   StaticSocketDataProvider data(data_reads, data_writes);
1339   session_deps.socket_factory.AddSocketDataProvider(&data);
1340 
1341   TestCompletionCallback callback;
1342 
1343   int rv = trans->Start(&request, &callback, NULL);
1344   EXPECT_EQ(ERR_IO_PENDING, rv);
1345 
1346   rv = callback.WaitForResult();
1347   EXPECT_EQ(expected_status, rv);
1348 }
1349 
ConnectStatusHelper(const MockRead & status)1350 void HttpNetworkTransactionTest::ConnectStatusHelper(const MockRead& status) {
1351   ConnectStatusHelperWithExpectedStatus(
1352       status, ERR_TUNNEL_CONNECTION_FAILED);
1353 }
1354 
TEST_F(HttpNetworkTransactionTest,ConnectStatus100)1355 TEST_F(HttpNetworkTransactionTest, ConnectStatus100) {
1356   ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
1357 }
1358 
TEST_F(HttpNetworkTransactionTest,ConnectStatus101)1359 TEST_F(HttpNetworkTransactionTest, ConnectStatus101) {
1360   ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
1361 }
1362 
TEST_F(HttpNetworkTransactionTest,ConnectStatus201)1363 TEST_F(HttpNetworkTransactionTest, ConnectStatus201) {
1364   ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
1365 }
1366 
TEST_F(HttpNetworkTransactionTest,ConnectStatus202)1367 TEST_F(HttpNetworkTransactionTest, ConnectStatus202) {
1368   ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
1369 }
1370 
TEST_F(HttpNetworkTransactionTest,ConnectStatus203)1371 TEST_F(HttpNetworkTransactionTest, ConnectStatus203) {
1372   ConnectStatusHelper(
1373       MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
1374 }
1375 
TEST_F(HttpNetworkTransactionTest,ConnectStatus204)1376 TEST_F(HttpNetworkTransactionTest, ConnectStatus204) {
1377   ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
1378 }
1379 
TEST_F(HttpNetworkTransactionTest,ConnectStatus205)1380 TEST_F(HttpNetworkTransactionTest, ConnectStatus205) {
1381   ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
1382 }
1383 
TEST_F(HttpNetworkTransactionTest,ConnectStatus206)1384 TEST_F(HttpNetworkTransactionTest, ConnectStatus206) {
1385   ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
1386 }
1387 
TEST_F(HttpNetworkTransactionTest,ConnectStatus300)1388 TEST_F(HttpNetworkTransactionTest, ConnectStatus300) {
1389   ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
1390 }
1391 
TEST_F(HttpNetworkTransactionTest,ConnectStatus301)1392 TEST_F(HttpNetworkTransactionTest, ConnectStatus301) {
1393   ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
1394 }
1395 
TEST_F(HttpNetworkTransactionTest,ConnectStatus302)1396 TEST_F(HttpNetworkTransactionTest, ConnectStatus302) {
1397   ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
1398 }
1399 
TEST_F(HttpNetworkTransactionTest,ConnectStatus303)1400 TEST_F(HttpNetworkTransactionTest, ConnectStatus303) {
1401   ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
1402 }
1403 
TEST_F(HttpNetworkTransactionTest,ConnectStatus304)1404 TEST_F(HttpNetworkTransactionTest, ConnectStatus304) {
1405   ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
1406 }
1407 
TEST_F(HttpNetworkTransactionTest,ConnectStatus305)1408 TEST_F(HttpNetworkTransactionTest, ConnectStatus305) {
1409   ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
1410 }
1411 
TEST_F(HttpNetworkTransactionTest,ConnectStatus306)1412 TEST_F(HttpNetworkTransactionTest, ConnectStatus306) {
1413   ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
1414 }
1415 
TEST_F(HttpNetworkTransactionTest,ConnectStatus307)1416 TEST_F(HttpNetworkTransactionTest, ConnectStatus307) {
1417   ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
1418 }
1419 
TEST_F(HttpNetworkTransactionTest,ConnectStatus400)1420 TEST_F(HttpNetworkTransactionTest, ConnectStatus400) {
1421   ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
1422 }
1423 
TEST_F(HttpNetworkTransactionTest,ConnectStatus401)1424 TEST_F(HttpNetworkTransactionTest, ConnectStatus401) {
1425   ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
1426 }
1427 
TEST_F(HttpNetworkTransactionTest,ConnectStatus402)1428 TEST_F(HttpNetworkTransactionTest, ConnectStatus402) {
1429   ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
1430 }
1431 
TEST_F(HttpNetworkTransactionTest,ConnectStatus403)1432 TEST_F(HttpNetworkTransactionTest, ConnectStatus403) {
1433   ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
1434 }
1435 
TEST_F(HttpNetworkTransactionTest,ConnectStatus404)1436 TEST_F(HttpNetworkTransactionTest, ConnectStatus404) {
1437   ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
1438 }
1439 
TEST_F(HttpNetworkTransactionTest,ConnectStatus405)1440 TEST_F(HttpNetworkTransactionTest, ConnectStatus405) {
1441   ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
1442 }
1443 
TEST_F(HttpNetworkTransactionTest,ConnectStatus406)1444 TEST_F(HttpNetworkTransactionTest, ConnectStatus406) {
1445   ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
1446 }
1447 
TEST_F(HttpNetworkTransactionTest,ConnectStatus407)1448 TEST_F(HttpNetworkTransactionTest, ConnectStatus407) {
1449   ConnectStatusHelperWithExpectedStatus(
1450       MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1451       ERR_PROXY_AUTH_REQUESTED);
1452 }
1453 
TEST_F(HttpNetworkTransactionTest,ConnectStatus408)1454 TEST_F(HttpNetworkTransactionTest, ConnectStatus408) {
1455   ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
1456 }
1457 
TEST_F(HttpNetworkTransactionTest,ConnectStatus409)1458 TEST_F(HttpNetworkTransactionTest, ConnectStatus409) {
1459   ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
1460 }
1461 
TEST_F(HttpNetworkTransactionTest,ConnectStatus410)1462 TEST_F(HttpNetworkTransactionTest, ConnectStatus410) {
1463   ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
1464 }
1465 
TEST_F(HttpNetworkTransactionTest,ConnectStatus411)1466 TEST_F(HttpNetworkTransactionTest, ConnectStatus411) {
1467   ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
1468 }
1469 
TEST_F(HttpNetworkTransactionTest,ConnectStatus412)1470 TEST_F(HttpNetworkTransactionTest, ConnectStatus412) {
1471   ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
1472 }
1473 
TEST_F(HttpNetworkTransactionTest,ConnectStatus413)1474 TEST_F(HttpNetworkTransactionTest, ConnectStatus413) {
1475   ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
1476 }
1477 
TEST_F(HttpNetworkTransactionTest,ConnectStatus414)1478 TEST_F(HttpNetworkTransactionTest, ConnectStatus414) {
1479   ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
1480 }
1481 
TEST_F(HttpNetworkTransactionTest,ConnectStatus415)1482 TEST_F(HttpNetworkTransactionTest, ConnectStatus415) {
1483   ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
1484 }
1485 
TEST_F(HttpNetworkTransactionTest,ConnectStatus416)1486 TEST_F(HttpNetworkTransactionTest, ConnectStatus416) {
1487   ConnectStatusHelper(
1488       MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
1489 }
1490 
TEST_F(HttpNetworkTransactionTest,ConnectStatus417)1491 TEST_F(HttpNetworkTransactionTest, ConnectStatus417) {
1492   ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
1493 }
1494 
TEST_F(HttpNetworkTransactionTest,ConnectStatus500)1495 TEST_F(HttpNetworkTransactionTest, ConnectStatus500) {
1496   ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
1497 }
1498 
TEST_F(HttpNetworkTransactionTest,ConnectStatus501)1499 TEST_F(HttpNetworkTransactionTest, ConnectStatus501) {
1500   ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
1501 }
1502 
TEST_F(HttpNetworkTransactionTest,ConnectStatus502)1503 TEST_F(HttpNetworkTransactionTest, ConnectStatus502) {
1504   ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
1505 }
1506 
TEST_F(HttpNetworkTransactionTest,ConnectStatus503)1507 TEST_F(HttpNetworkTransactionTest, ConnectStatus503) {
1508   ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
1509 }
1510 
TEST_F(HttpNetworkTransactionTest,ConnectStatus504)1511 TEST_F(HttpNetworkTransactionTest, ConnectStatus504) {
1512   ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
1513 }
1514 
TEST_F(HttpNetworkTransactionTest,ConnectStatus505)1515 TEST_F(HttpNetworkTransactionTest, ConnectStatus505) {
1516   ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
1517 }
1518 
1519 // Test the flow when both the proxy server AND origin server require
1520 // authentication. Again, this uses basic auth for both since that is
1521 // the simplest to mock.
TEST_F(HttpNetworkTransactionTest,BasicAuthProxyThenServer)1522 TEST_F(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
1523   SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
1524 
1525   // Configure against proxy server "myproxy:70".
1526   scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
1527       CreateSession(&session_deps)));
1528 
1529   HttpRequestInfo request;
1530   request.method = "GET";
1531   request.url = GURL("http://www.google.com/");
1532   request.load_flags = 0;
1533 
1534   MockWrite data_writes1[] = {
1535     MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1536               "Host: www.google.com\r\n"
1537               "Proxy-Connection: keep-alive\r\n\r\n"),
1538   };
1539 
1540   MockRead data_reads1[] = {
1541     MockRead("HTTP/1.0 407 Unauthorized\r\n"),
1542     // Give a couple authenticate options (only the middle one is actually
1543     // supported).
1544     MockRead("Proxy-Authenticate: Basic invalid\r\n"),  // Malformed.
1545     MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1546     MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
1547     MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1548     // Large content-length -- won't matter, as connection will be reset.
1549     MockRead("Content-Length: 10000\r\n\r\n"),
1550     MockRead(false, ERR_FAILED),
1551   };
1552 
1553   // After calling trans->RestartWithAuth() the first time, this is the
1554   // request we should be issuing -- the final header line contains the
1555   // proxy's credentials.
1556   MockWrite data_writes2[] = {
1557     MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1558               "Host: www.google.com\r\n"
1559               "Proxy-Connection: keep-alive\r\n"
1560               "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1561   };
1562 
1563   // Now the proxy server lets the request pass through to origin server.
1564   // The origin server responds with a 401.
1565   MockRead data_reads2[] = {
1566     MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1567     // Note: We are using the same realm-name as the proxy server. This is
1568     // completely valid, as realms are unique across hosts.
1569     MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1570     MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1571     MockRead("Content-Length: 2000\r\n\r\n"),
1572     MockRead(false, ERR_FAILED),  // Won't be reached.
1573   };
1574 
1575   // After calling trans->RestartWithAuth() the second time, we should send
1576   // the credentials for both the proxy and origin server.
1577   MockWrite data_writes3[] = {
1578     MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1579               "Host: www.google.com\r\n"
1580               "Proxy-Connection: keep-alive\r\n"
1581               "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
1582               "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
1583   };
1584 
1585   // Lastly we get the desired content.
1586   MockRead data_reads3[] = {
1587     MockRead("HTTP/1.0 200 OK\r\n"),
1588     MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1589     MockRead("Content-Length: 100\r\n\r\n"),
1590     MockRead(false, OK),
1591   };
1592 
1593   StaticSocketDataProvider data1(data_reads1, data_writes1);
1594   StaticSocketDataProvider data2(data_reads2, data_writes2);
1595   StaticSocketDataProvider data3(data_reads3, data_writes3);
1596   session_deps.socket_factory.AddSocketDataProvider(&data1);
1597   session_deps.socket_factory.AddSocketDataProvider(&data2);
1598   session_deps.socket_factory.AddSocketDataProvider(&data3);
1599 
1600   TestCompletionCallback callback1;
1601 
1602   int rv = trans->Start(&request, &callback1, NULL);
1603   EXPECT_EQ(ERR_IO_PENDING, rv);
1604 
1605   rv = callback1.WaitForResult();
1606   EXPECT_EQ(OK, rv);
1607 
1608   const HttpResponseInfo* response = trans->GetResponseInfo();
1609   EXPECT_FALSE(response == NULL);
1610 
1611   // The password prompt info should have been set in response->auth_challenge.
1612   EXPECT_FALSE(response->auth_challenge.get() == NULL);
1613 
1614   EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
1615   EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1616   EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1617 
1618   TestCompletionCallback callback2;
1619 
1620   rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
1621   EXPECT_EQ(ERR_IO_PENDING, rv);
1622 
1623   rv = callback2.WaitForResult();
1624   EXPECT_EQ(OK, rv);
1625 
1626   response = trans->GetResponseInfo();
1627   EXPECT_FALSE(response == NULL);
1628   EXPECT_FALSE(response->auth_challenge.get() == NULL);
1629 
1630   EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
1631   EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1632   EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1633 
1634   TestCompletionCallback callback3;
1635 
1636   rv = trans->RestartWithAuth(L"foo2", L"bar2", &callback3);
1637   EXPECT_EQ(ERR_IO_PENDING, rv);
1638 
1639   rv = callback3.WaitForResult();
1640   EXPECT_EQ(OK, rv);
1641 
1642   response = trans->GetResponseInfo();
1643   EXPECT_TRUE(response->auth_challenge.get() == NULL);
1644   EXPECT_EQ(100, response->headers->GetContentLength());
1645 }
1646 
1647 // For the NTLM implementation using SSPI, we skip the NTLM tests since we
1648 // can't hook into its internals to cause it to generate predictable NTLM
1649 // authorization headers.
1650 #if defined(NTLM_PORTABLE)
1651 // The NTLM authentication unit tests were generated by capturing the HTTP
1652 // requests and responses using Fiddler 2 and inspecting the generated random
1653 // bytes in the debugger.
1654 
1655 // Enter the correct password and authenticate successfully.
TEST_F(HttpNetworkTransactionTest,NTLMAuth1)1656 TEST_F(HttpNetworkTransactionTest, NTLMAuth1) {
1657   HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom1,
1658                                                          MockGetHostName);
1659   SessionDependencies session_deps;
1660   scoped_ptr<HttpTransaction> trans(
1661       new HttpNetworkTransaction(CreateSession(&session_deps)));
1662 
1663   HttpRequestInfo request;
1664   request.method = "GET";
1665   request.url = GURL("http://172.22.68.17/kids/login.aspx");
1666   request.load_flags = 0;
1667 
1668   MockWrite data_writes1[] = {
1669     MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1670               "Host: 172.22.68.17\r\n"
1671               "Connection: keep-alive\r\n\r\n"),
1672   };
1673 
1674   MockRead data_reads1[] = {
1675     MockRead("HTTP/1.1 401 Access Denied\r\n"),
1676     // Negotiate and NTLM are often requested together.  We only support NTLM.
1677     MockRead("WWW-Authenticate: Negotiate\r\n"),
1678     MockRead("WWW-Authenticate: NTLM\r\n"),
1679     MockRead("Connection: close\r\n"),
1680     MockRead("Content-Length: 42\r\n"),
1681     MockRead("Content-Type: text/html\r\n\r\n"),
1682     // Missing content -- won't matter, as connection will be reset.
1683     MockRead(false, ERR_UNEXPECTED),
1684   };
1685 
1686   MockWrite data_writes2[] = {
1687     // After restarting with a null identity, this is the
1688     // request we should be issuing -- the final header line contains a Type
1689     // 1 message.
1690     MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1691               "Host: 172.22.68.17\r\n"
1692               "Connection: keep-alive\r\n"
1693               "Authorization: NTLM "
1694               "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
1695 
1696     // After calling trans->RestartWithAuth(), we should send a Type 3 message
1697     // (the credentials for the origin server).  The second request continues
1698     // on the same connection.
1699     MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1700               "Host: 172.22.68.17\r\n"
1701               "Connection: keep-alive\r\n"
1702               "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
1703               "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
1704               "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
1705               "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
1706               "ahlhx5I=\r\n\r\n"),
1707   };
1708 
1709   MockRead data_reads2[] = {
1710     // The origin server responds with a Type 2 message.
1711     MockRead("HTTP/1.1 401 Access Denied\r\n"),
1712     MockRead("WWW-Authenticate: NTLM "
1713              "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
1714              "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
1715              "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
1716              "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
1717              "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
1718              "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
1719              "BtAAAAAAA=\r\n"),
1720     MockRead("Content-Length: 42\r\n"),
1721     MockRead("Content-Type: text/html\r\n\r\n"),
1722     MockRead("You are not authorized to view this page\r\n"),
1723 
1724     // Lastly we get the desired content.
1725     MockRead("HTTP/1.1 200 OK\r\n"),
1726     MockRead("Content-Type: text/html; charset=utf-8\r\n"),
1727     MockRead("Content-Length: 13\r\n\r\n"),
1728     MockRead("Please Login\r\n"),
1729     MockRead(false, OK),
1730   };
1731 
1732   StaticSocketDataProvider data1(data_reads1, data_writes1);
1733   StaticSocketDataProvider data2(data_reads2, data_writes2);
1734   session_deps.socket_factory.AddSocketDataProvider(&data1);
1735   session_deps.socket_factory.AddSocketDataProvider(&data2);
1736 
1737   TestCompletionCallback callback1;
1738 
1739   int rv = trans->Start(&request, &callback1, NULL);
1740   EXPECT_EQ(ERR_IO_PENDING, rv);
1741 
1742   rv = callback1.WaitForResult();
1743   EXPECT_EQ(OK, rv);
1744 
1745   EXPECT_TRUE(trans->IsReadyToRestartForAuth());
1746   TestCompletionCallback callback2;
1747   rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
1748   EXPECT_EQ(ERR_IO_PENDING, rv);
1749   rv = callback2.WaitForResult();
1750   EXPECT_EQ(OK, rv);
1751   EXPECT_FALSE(trans->IsReadyToRestartForAuth());
1752 
1753   const HttpResponseInfo* response = trans->GetResponseInfo();
1754   EXPECT_FALSE(response == NULL);
1755 
1756   // The password prompt info should have been set in response->auth_challenge.
1757   EXPECT_FALSE(response->auth_challenge.get() == NULL);
1758 
1759   EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
1760   EXPECT_EQ(L"", response->auth_challenge->realm);
1761   EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
1762 
1763   TestCompletionCallback callback3;
1764 
1765   rv = trans->RestartWithAuth(L"testing-ntlm", L"testing-ntlm", &callback3);
1766   EXPECT_EQ(ERR_IO_PENDING, rv);
1767 
1768   rv = callback3.WaitForResult();
1769   EXPECT_EQ(OK, rv);
1770 
1771   response = trans->GetResponseInfo();
1772   EXPECT_TRUE(response->auth_challenge.get() == NULL);
1773   EXPECT_EQ(13, response->headers->GetContentLength());
1774 }
1775 
1776 // Enter a wrong password, and then the correct one.
TEST_F(HttpNetworkTransactionTest,NTLMAuth2)1777 TEST_F(HttpNetworkTransactionTest, NTLMAuth2) {
1778   HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom2,
1779                                                          MockGetHostName);
1780   SessionDependencies session_deps;
1781   scoped_ptr<HttpTransaction> trans(
1782       new HttpNetworkTransaction(CreateSession(&session_deps)));
1783 
1784   HttpRequestInfo request;
1785   request.method = "GET";
1786   request.url = GURL("http://172.22.68.17/kids/login.aspx");
1787   request.load_flags = 0;
1788 
1789   MockWrite data_writes1[] = {
1790     MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1791               "Host: 172.22.68.17\r\n"
1792               "Connection: keep-alive\r\n\r\n"),
1793   };
1794 
1795   MockRead data_reads1[] = {
1796     MockRead("HTTP/1.1 401 Access Denied\r\n"),
1797     // Negotiate and NTLM are often requested together.  We only support NTLM.
1798     MockRead("WWW-Authenticate: Negotiate\r\n"),
1799     MockRead("WWW-Authenticate: NTLM\r\n"),
1800     MockRead("Connection: close\r\n"),
1801     MockRead("Content-Length: 42\r\n"),
1802     MockRead("Content-Type: text/html\r\n\r\n"),
1803     // Missing content -- won't matter, as connection will be reset.
1804     MockRead(false, ERR_UNEXPECTED),
1805   };
1806 
1807   MockWrite data_writes2[] = {
1808     // After restarting with a null identity, this is the
1809     // request we should be issuing -- the final header line contains a Type
1810     // 1 message.
1811     MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1812               "Host: 172.22.68.17\r\n"
1813               "Connection: keep-alive\r\n"
1814               "Authorization: NTLM "
1815               "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
1816 
1817     // After calling trans->RestartWithAuth(), we should send a Type 3 message
1818     // (the credentials for the origin server).  The second request continues
1819     // on the same connection.
1820     MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1821               "Host: 172.22.68.17\r\n"
1822               "Connection: keep-alive\r\n"
1823               "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
1824               "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
1825               "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
1826               "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
1827               "4Ww7b7E=\r\n\r\n"),
1828   };
1829 
1830   MockRead data_reads2[] = {
1831     // The origin server responds with a Type 2 message.
1832     MockRead("HTTP/1.1 401 Access Denied\r\n"),
1833     MockRead("WWW-Authenticate: NTLM "
1834              "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
1835              "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
1836              "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
1837              "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
1838              "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
1839              "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
1840              "BtAAAAAAA=\r\n"),
1841     MockRead("Content-Length: 42\r\n"),
1842     MockRead("Content-Type: text/html\r\n\r\n"),
1843     MockRead("You are not authorized to view this page\r\n"),
1844 
1845     // Wrong password.
1846     MockRead("HTTP/1.1 401 Access Denied\r\n"),
1847     MockRead("WWW-Authenticate: Negotiate\r\n"),
1848     MockRead("WWW-Authenticate: NTLM\r\n"),
1849     MockRead("Connection: close\r\n"),
1850     MockRead("Content-Length: 42\r\n"),
1851     MockRead("Content-Type: text/html\r\n\r\n"),
1852     // Missing content -- won't matter, as connection will be reset.
1853     MockRead(false, ERR_UNEXPECTED),
1854   };
1855 
1856   MockWrite data_writes3[] = {
1857     // After restarting with a null identity, this is the
1858     // request we should be issuing -- the final header line contains a Type
1859     // 1 message.
1860     MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1861               "Host: 172.22.68.17\r\n"
1862               "Connection: keep-alive\r\n"
1863               "Authorization: NTLM "
1864               "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
1865 
1866     // After calling trans->RestartWithAuth(), we should send a Type 3 message
1867     // (the credentials for the origin server).  The second request continues
1868     // on the same connection.
1869     MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1870               "Host: 172.22.68.17\r\n"
1871               "Connection: keep-alive\r\n"
1872               "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
1873               "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
1874               "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
1875               "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
1876               "+4MUm7c=\r\n\r\n"),
1877   };
1878 
1879   MockRead data_reads3[] = {
1880     // The origin server responds with a Type 2 message.
1881     MockRead("HTTP/1.1 401 Access Denied\r\n"),
1882     MockRead("WWW-Authenticate: NTLM "
1883              "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
1884              "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
1885              "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
1886              "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
1887              "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
1888              "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
1889              "BtAAAAAAA=\r\n"),
1890     MockRead("Content-Length: 42\r\n"),
1891     MockRead("Content-Type: text/html\r\n\r\n"),
1892     MockRead("You are not authorized to view this page\r\n"),
1893 
1894     // Lastly we get the desired content.
1895     MockRead("HTTP/1.1 200 OK\r\n"),
1896     MockRead("Content-Type: text/html; charset=utf-8\r\n"),
1897     MockRead("Content-Length: 13\r\n\r\n"),
1898     MockRead("Please Login\r\n"),
1899     MockRead(false, OK),
1900   };
1901 
1902   StaticSocketDataProvider data1(data_reads1, data_writes1);
1903   StaticSocketDataProvider data2(data_reads2, data_writes2);
1904   StaticSocketDataProvider data3(data_reads3, data_writes3);
1905   session_deps.socket_factory.AddSocketDataProvider(&data1);
1906   session_deps.socket_factory.AddSocketDataProvider(&data2);
1907   session_deps.socket_factory.AddSocketDataProvider(&data3);
1908 
1909   TestCompletionCallback callback1;
1910 
1911   int rv = trans->Start(&request, &callback1, NULL);
1912   EXPECT_EQ(ERR_IO_PENDING, rv);
1913 
1914   rv = callback1.WaitForResult();
1915   EXPECT_EQ(OK, rv);
1916 
1917   EXPECT_TRUE(trans->IsReadyToRestartForAuth());
1918   TestCompletionCallback callback2;
1919   rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
1920   EXPECT_EQ(ERR_IO_PENDING, rv);
1921   rv = callback2.WaitForResult();
1922   EXPECT_EQ(OK, rv);
1923   EXPECT_FALSE(trans->IsReadyToRestartForAuth());
1924 
1925   const HttpResponseInfo* response = trans->GetResponseInfo();
1926   EXPECT_FALSE(response == NULL);
1927 
1928   // The password prompt info should have been set in response->auth_challenge.
1929   EXPECT_FALSE(response->auth_challenge.get() == NULL);
1930 
1931   EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
1932   EXPECT_EQ(L"", response->auth_challenge->realm);
1933   EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
1934 
1935   TestCompletionCallback callback3;
1936 
1937   // Enter the wrong password.
1938   rv = trans->RestartWithAuth(L"testing-ntlm", L"wrongpassword", &callback3);
1939   EXPECT_EQ(ERR_IO_PENDING, rv);
1940 
1941   rv = callback3.WaitForResult();
1942   EXPECT_EQ(OK, rv);
1943 
1944   EXPECT_TRUE(trans->IsReadyToRestartForAuth());
1945   TestCompletionCallback callback4;
1946   rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback4);
1947   EXPECT_EQ(ERR_IO_PENDING, rv);
1948   rv = callback4.WaitForResult();
1949   EXPECT_EQ(OK, rv);
1950   EXPECT_FALSE(trans->IsReadyToRestartForAuth());
1951 
1952   response = trans->GetResponseInfo();
1953   EXPECT_FALSE(response == NULL);
1954 
1955   // The password prompt info should have been set in response->auth_challenge.
1956   EXPECT_FALSE(response->auth_challenge.get() == NULL);
1957 
1958   EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
1959   EXPECT_EQ(L"", response->auth_challenge->realm);
1960   EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
1961 
1962   TestCompletionCallback callback5;
1963 
1964   // Now enter the right password.
1965   rv = trans->RestartWithAuth(L"testing-ntlm", L"testing-ntlm", &callback5);
1966   EXPECT_EQ(ERR_IO_PENDING, rv);
1967 
1968   rv = callback5.WaitForResult();
1969   EXPECT_EQ(OK, rv);
1970 
1971   response = trans->GetResponseInfo();
1972   EXPECT_TRUE(response->auth_challenge.get() == NULL);
1973   EXPECT_EQ(13, response->headers->GetContentLength());
1974 }
1975 #endif  // NTLM_PORTABLE
1976 
1977 // Test reading a server response which has only headers, and no body.
1978 // After some maximum number of bytes is consumed, the transaction should
1979 // fail with ERR_RESPONSE_HEADERS_TOO_BIG.
TEST_F(HttpNetworkTransactionTest,LargeHeadersNoBody)1980 TEST_F(HttpNetworkTransactionTest, LargeHeadersNoBody) {
1981   SessionDependencies session_deps;
1982   scoped_ptr<HttpTransaction> trans(
1983       new HttpNetworkTransaction(CreateSession(&session_deps)));
1984 
1985   HttpRequestInfo request;
1986   request.method = "GET";
1987   request.url = GURL("http://www.google.com/");
1988   request.load_flags = 0;
1989 
1990   // Respond with 300 kb of headers (we should fail after 256 kb).
1991   std::string large_headers_string;
1992   FillLargeHeadersString(&large_headers_string, 300 * 1024);
1993 
1994   MockRead data_reads[] = {
1995     MockRead("HTTP/1.0 200 OK\r\n"),
1996     MockRead(true, large_headers_string.data(), large_headers_string.size()),
1997     MockRead("\r\nBODY"),
1998     MockRead(false, OK),
1999   };
2000   StaticSocketDataProvider data(data_reads, NULL);
2001   session_deps.socket_factory.AddSocketDataProvider(&data);
2002 
2003   TestCompletionCallback callback;
2004 
2005   int rv = trans->Start(&request, &callback, NULL);
2006   EXPECT_EQ(ERR_IO_PENDING, rv);
2007 
2008   rv = callback.WaitForResult();
2009   EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG, rv);
2010 
2011   const HttpResponseInfo* response = trans->GetResponseInfo();
2012   EXPECT_TRUE(response == NULL);
2013 }
2014 
2015 // Make sure that we don't try to reuse a TCPClientSocket when failing to
2016 // establish tunnel.
2017 // http://code.google.com/p/chromium/issues/detail?id=3772
TEST_F(HttpNetworkTransactionTest,DontRecycleTCPSocketForSSLTunnel)2018 TEST_F(HttpNetworkTransactionTest, DontRecycleTCPSocketForSSLTunnel) {
2019   // Configure against proxy server "myproxy:70".
2020   SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
2021 
2022   scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2023 
2024   scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2025 
2026   HttpRequestInfo request;
2027   request.method = "GET";
2028   request.url = GURL("https://www.google.com/");
2029   request.load_flags = 0;
2030 
2031   // Since we have proxy, should try to establish tunnel.
2032   MockWrite data_writes1[] = {
2033     MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2034               "Host: www.google.com\r\n"
2035               "Proxy-Connection: keep-alive\r\n\r\n"),
2036   };
2037 
2038   // The proxy responds to the connect with a 404, using a persistent
2039   // connection. Usually a proxy would return 501 (not implemented),
2040   // or 200 (tunnel established).
2041   MockRead data_reads1[] = {
2042     MockRead("HTTP/1.1 404 Not Found\r\n"),
2043     MockRead("Content-Length: 10\r\n\r\n"),
2044     MockRead(false, ERR_UNEXPECTED),  // Should not be reached.
2045   };
2046 
2047   StaticSocketDataProvider data1(data_reads1, data_writes1);
2048   session_deps.socket_factory.AddSocketDataProvider(&data1);
2049 
2050   TestCompletionCallback callback1;
2051 
2052   int rv = trans->Start(&request, &callback1, NULL);
2053   EXPECT_EQ(ERR_IO_PENDING, rv);
2054 
2055   rv = callback1.WaitForResult();
2056   EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
2057 
2058   const HttpResponseInfo* response = trans->GetResponseInfo();
2059   EXPECT_TRUE(response == NULL);
2060 
2061   // Empty the current queue.  This is necessary because idle sockets are
2062   // added to the connection pool asynchronously with a PostTask.
2063   MessageLoop::current()->RunAllPending();
2064 
2065   // We now check to make sure the TCPClientSocket was not added back to
2066   // the pool.
2067   EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
2068   trans.reset();
2069   MessageLoop::current()->RunAllPending();
2070   // Make sure that the socket didn't get recycled after calling the destructor.
2071   EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
2072 }
2073 
2074 // Make sure that we recycle a socket after reading all of the response body.
TEST_F(HttpNetworkTransactionTest,RecycleSocket)2075 TEST_F(HttpNetworkTransactionTest, RecycleSocket) {
2076   SessionDependencies session_deps;
2077   scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2078 
2079   scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2080 
2081   HttpRequestInfo request;
2082   request.method = "GET";
2083   request.url = GURL("http://www.google.com/");
2084   request.load_flags = 0;
2085 
2086   MockRead data_reads[] = {
2087     // A part of the response body is received with the response headers.
2088     MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
2089     // The rest of the response body is received in two parts.
2090     MockRead("lo"),
2091     MockRead(" world"),
2092     MockRead("junk"),  // Should not be read!!
2093     MockRead(false, OK),
2094   };
2095 
2096   StaticSocketDataProvider data(data_reads, NULL);
2097   session_deps.socket_factory.AddSocketDataProvider(&data);
2098 
2099   TestCompletionCallback callback;
2100 
2101   int rv = trans->Start(&request, &callback, NULL);
2102   EXPECT_EQ(ERR_IO_PENDING, rv);
2103 
2104   rv = callback.WaitForResult();
2105   EXPECT_EQ(OK, rv);
2106 
2107   const HttpResponseInfo* response = trans->GetResponseInfo();
2108   EXPECT_TRUE(response != NULL);
2109 
2110   EXPECT_TRUE(response->headers != NULL);
2111   std::string status_line = response->headers->GetStatusLine();
2112   EXPECT_EQ("HTTP/1.1 200 OK", status_line);
2113 
2114   EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
2115 
2116   std::string response_data;
2117   rv = ReadTransaction(trans.get(), &response_data);
2118   EXPECT_EQ(OK, rv);
2119   EXPECT_EQ("hello world", response_data);
2120 
2121   // Empty the current queue.  This is necessary because idle sockets are
2122   // added to the connection pool asynchronously with a PostTask.
2123   MessageLoop::current()->RunAllPending();
2124 
2125   // We now check to make sure the socket was added back to the pool.
2126   EXPECT_EQ(1, session->tcp_socket_pool()->IdleSocketCount());
2127 }
2128 
2129 // Make sure that we recycle a socket after a zero-length response.
2130 // http://crbug.com/9880
TEST_F(HttpNetworkTransactionTest,RecycleSocketAfterZeroContentLength)2131 TEST_F(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
2132   SessionDependencies session_deps;
2133   scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2134 
2135   scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2136 
2137   HttpRequestInfo request;
2138   request.method = "GET";
2139   request.url = GURL("http://www.google.com/csi?v=3&s=web&action=&"
2140                      "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
2141                      "e=17259,18167,19592,19773,19981,20133,20173,20233&"
2142                      "rt=prt.2642,ol.2649,xjs.2951");
2143   request.load_flags = 0;
2144 
2145   MockRead data_reads[] = {
2146     MockRead("HTTP/1.1 204 No Content\r\n"
2147              "Content-Length: 0\r\n"
2148              "Content-Type: text/html\r\n\r\n"),
2149     MockRead("junk"),  // Should not be read!!
2150     MockRead(false, OK),
2151   };
2152 
2153   StaticSocketDataProvider data(data_reads, NULL);
2154   session_deps.socket_factory.AddSocketDataProvider(&data);
2155 
2156   TestCompletionCallback callback;
2157 
2158   int rv = trans->Start(&request, &callback, NULL);
2159   EXPECT_EQ(ERR_IO_PENDING, rv);
2160 
2161   rv = callback.WaitForResult();
2162   EXPECT_EQ(OK, rv);
2163 
2164   const HttpResponseInfo* response = trans->GetResponseInfo();
2165   EXPECT_TRUE(response != NULL);
2166 
2167   EXPECT_TRUE(response->headers != NULL);
2168   std::string status_line = response->headers->GetStatusLine();
2169   EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
2170 
2171   EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
2172 
2173   std::string response_data;
2174   rv = ReadTransaction(trans.get(), &response_data);
2175   EXPECT_EQ(OK, rv);
2176   EXPECT_EQ("", response_data);
2177 
2178   // Empty the current queue.  This is necessary because idle sockets are
2179   // added to the connection pool asynchronously with a PostTask.
2180   MessageLoop::current()->RunAllPending();
2181 
2182   // We now check to make sure the socket was added back to the pool.
2183   EXPECT_EQ(1, session->tcp_socket_pool()->IdleSocketCount());
2184 }
2185 
TEST_F(HttpNetworkTransactionTest,ResendRequestOnWriteBodyError)2186 TEST_F(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
2187   HttpRequestInfo request[2];
2188   // Transaction 1: a GET request that succeeds.  The socket is recycled
2189   // after use.
2190   request[0].method = "GET";
2191   request[0].url = GURL("http://www.google.com/");
2192   request[0].load_flags = 0;
2193   // Transaction 2: a POST request.  Reuses the socket kept alive from
2194   // transaction 1.  The first attempts fails when writing the POST data.
2195   // This causes the transaction to retry with a new socket.  The second
2196   // attempt succeeds.
2197   request[1].method = "POST";
2198   request[1].url = GURL("http://www.google.com/login.cgi");
2199   request[1].upload_data = new UploadData;
2200   request[1].upload_data->AppendBytes("foo", 3);
2201   request[1].load_flags = 0;
2202 
2203   SessionDependencies session_deps;
2204   scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
2205 
2206   // The first socket is used for transaction 1 and the first attempt of
2207   // transaction 2.
2208 
2209   // The response of transaction 1.
2210   MockRead data_reads1[] = {
2211     MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
2212     MockRead("hello world"),
2213     MockRead(false, OK),
2214   };
2215   // The mock write results of transaction 1 and the first attempt of
2216   // transaction 2.
2217   MockWrite data_writes1[] = {
2218     MockWrite(false, 64),  // GET
2219     MockWrite(false, 93),  // POST
2220     MockWrite(false, ERR_CONNECTION_ABORTED),  // POST data
2221   };
2222   StaticSocketDataProvider data1(data_reads1, data_writes1);
2223 
2224   // The second socket is used for the second attempt of transaction 2.
2225 
2226   // The response of transaction 2.
2227   MockRead data_reads2[] = {
2228     MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
2229     MockRead("welcome"),
2230     MockRead(false, OK),
2231   };
2232   // The mock write results of the second attempt of transaction 2.
2233   MockWrite data_writes2[] = {
2234     MockWrite(false, 93),  // POST
2235     MockWrite(false, 3),  // POST data
2236   };
2237   StaticSocketDataProvider data2(data_reads2, data_writes2);
2238 
2239   session_deps.socket_factory.AddSocketDataProvider(&data1);
2240   session_deps.socket_factory.AddSocketDataProvider(&data2);
2241 
2242   const char* kExpectedResponseData[] = {
2243     "hello world", "welcome"
2244   };
2245 
2246   for (int i = 0; i < 2; ++i) {
2247     scoped_ptr<HttpTransaction> trans(
2248         new HttpNetworkTransaction(session));
2249 
2250     TestCompletionCallback callback;
2251 
2252     int rv = trans->Start(&request[i], &callback, NULL);
2253     EXPECT_EQ(ERR_IO_PENDING, rv);
2254 
2255     rv = callback.WaitForResult();
2256     EXPECT_EQ(OK, rv);
2257 
2258     const HttpResponseInfo* response = trans->GetResponseInfo();
2259     EXPECT_TRUE(response != NULL);
2260 
2261     EXPECT_TRUE(response->headers != NULL);
2262     EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2263 
2264     std::string response_data;
2265     rv = ReadTransaction(trans.get(), &response_data);
2266     EXPECT_EQ(OK, rv);
2267     EXPECT_EQ(kExpectedResponseData[i], response_data);
2268   }
2269 }
2270 
2271 // Test the request-challenge-retry sequence for basic auth when there is
2272 // an identity in the URL. The request should be sent as normal, but when
2273 // it fails the identity from the URL is used to answer the challenge.
TEST_F(HttpNetworkTransactionTest,AuthIdentityInURL)2274 TEST_F(HttpNetworkTransactionTest, AuthIdentityInURL) {
2275   SessionDependencies session_deps;
2276   scoped_ptr<HttpTransaction> trans(
2277       new HttpNetworkTransaction(CreateSession(&session_deps)));
2278 
2279   HttpRequestInfo request;
2280   request.method = "GET";
2281   // Note: the URL has a username:password in it.
2282   request.url = GURL("http://foo:b@r@www.google.com/");
2283 
2284   // The password contains an escaped character -- for this test to pass it
2285   // will need to be unescaped by HttpNetworkTransaction.
2286   EXPECT_EQ("b%40r", request.url.password());
2287 
2288   request.load_flags = LOAD_NORMAL;
2289 
2290   MockWrite data_writes1[] = {
2291     MockWrite("GET / HTTP/1.1\r\n"
2292               "Host: www.google.com\r\n"
2293               "Connection: keep-alive\r\n\r\n"),
2294   };
2295 
2296   MockRead data_reads1[] = {
2297     MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2298     MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2299     MockRead("Content-Length: 10\r\n\r\n"),
2300     MockRead(false, ERR_FAILED),
2301   };
2302 
2303   // After the challenge above, the transaction will be restarted using the
2304   // identity from the url (foo, b@r) to answer the challenge.
2305   MockWrite data_writes2[] = {
2306     MockWrite("GET / HTTP/1.1\r\n"
2307               "Host: www.google.com\r\n"
2308               "Connection: keep-alive\r\n"
2309               "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
2310   };
2311 
2312   MockRead data_reads2[] = {
2313     MockRead("HTTP/1.0 200 OK\r\n"),
2314     MockRead("Content-Length: 100\r\n\r\n"),
2315     MockRead(false, OK),
2316   };
2317 
2318   StaticSocketDataProvider data1(data_reads1, data_writes1);
2319   StaticSocketDataProvider data2(data_reads2, data_writes2);
2320   session_deps.socket_factory.AddSocketDataProvider(&data1);
2321   session_deps.socket_factory.AddSocketDataProvider(&data2);
2322 
2323   TestCompletionCallback callback1;
2324 
2325   int rv = trans->Start(&request, &callback1, NULL);
2326   EXPECT_EQ(ERR_IO_PENDING, rv);
2327 
2328   rv = callback1.WaitForResult();
2329   EXPECT_EQ(OK, rv);
2330 
2331   EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2332   TestCompletionCallback callback2;
2333   rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
2334   EXPECT_EQ(ERR_IO_PENDING, rv);
2335   rv = callback2.WaitForResult();
2336   EXPECT_EQ(OK, rv);
2337   EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2338 
2339   const HttpResponseInfo* response = trans->GetResponseInfo();
2340   EXPECT_FALSE(response == NULL);
2341 
2342   // There is no challenge info, since the identity in URL worked.
2343   EXPECT_TRUE(response->auth_challenge.get() == NULL);
2344 
2345   EXPECT_EQ(100, response->headers->GetContentLength());
2346 
2347   // Empty the current queue.
2348   MessageLoop::current()->RunAllPending();
2349 }
2350 
2351 // Test the request-challenge-retry sequence for basic auth when there is
2352 // an incorrect identity in the URL. The identity from the URL should be used
2353 // only once.
TEST_F(HttpNetworkTransactionTest,WrongAuthIdentityInURL)2354 TEST_F(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
2355   SessionDependencies session_deps;
2356   scoped_ptr<HttpTransaction> trans(
2357       new HttpNetworkTransaction(CreateSession(&session_deps)));
2358 
2359   HttpRequestInfo request;
2360   request.method = "GET";
2361   // Note: the URL has a username:password in it.  The password "baz" is
2362   // wrong (should be "bar").
2363   request.url = GURL("http://foo:baz@www.google.com/");
2364 
2365   request.load_flags = LOAD_NORMAL;
2366 
2367   MockWrite data_writes1[] = {
2368     MockWrite("GET / HTTP/1.1\r\n"
2369               "Host: www.google.com\r\n"
2370               "Connection: keep-alive\r\n\r\n"),
2371   };
2372 
2373   MockRead data_reads1[] = {
2374     MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2375     MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2376     MockRead("Content-Length: 10\r\n\r\n"),
2377     MockRead(false, ERR_FAILED),
2378   };
2379 
2380   // After the challenge above, the transaction will be restarted using the
2381   // identity from the url (foo, baz) to answer the challenge.
2382   MockWrite data_writes2[] = {
2383     MockWrite("GET / HTTP/1.1\r\n"
2384               "Host: www.google.com\r\n"
2385               "Connection: keep-alive\r\n"
2386               "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
2387   };
2388 
2389   MockRead data_reads2[] = {
2390     MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2391     MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2392     MockRead("Content-Length: 10\r\n\r\n"),
2393     MockRead(false, ERR_FAILED),
2394   };
2395 
2396   // After the challenge above, the transaction will be restarted using the
2397   // identity supplied by the user (foo, bar) to answer the challenge.
2398   MockWrite data_writes3[] = {
2399     MockWrite("GET / HTTP/1.1\r\n"
2400               "Host: www.google.com\r\n"
2401               "Connection: keep-alive\r\n"
2402               "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2403   };
2404 
2405   MockRead data_reads3[] = {
2406     MockRead("HTTP/1.0 200 OK\r\n"),
2407     MockRead("Content-Length: 100\r\n\r\n"),
2408     MockRead(false, OK),
2409   };
2410 
2411   StaticSocketDataProvider data1(data_reads1, data_writes1);
2412   StaticSocketDataProvider data2(data_reads2, data_writes2);
2413   StaticSocketDataProvider data3(data_reads3, data_writes3);
2414   session_deps.socket_factory.AddSocketDataProvider(&data1);
2415   session_deps.socket_factory.AddSocketDataProvider(&data2);
2416   session_deps.socket_factory.AddSocketDataProvider(&data3);
2417 
2418   TestCompletionCallback callback1;
2419 
2420   int rv = trans->Start(&request, &callback1, NULL);
2421   EXPECT_EQ(ERR_IO_PENDING, rv);
2422 
2423   rv = callback1.WaitForResult();
2424   EXPECT_EQ(OK, rv);
2425 
2426   EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2427   TestCompletionCallback callback2;
2428   rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
2429   EXPECT_EQ(ERR_IO_PENDING, rv);
2430   rv = callback2.WaitForResult();
2431   EXPECT_EQ(OK, rv);
2432   EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2433 
2434   const HttpResponseInfo* response = trans->GetResponseInfo();
2435   EXPECT_FALSE(response == NULL);
2436   // The password prompt info should have been set in response->auth_challenge.
2437   EXPECT_FALSE(response->auth_challenge.get() == NULL);
2438 
2439   EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
2440   EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2441   EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2442 
2443   TestCompletionCallback callback3;
2444   rv = trans->RestartWithAuth(L"foo", L"bar", &callback3);
2445   EXPECT_EQ(ERR_IO_PENDING, rv);
2446   rv = callback3.WaitForResult();
2447   EXPECT_EQ(OK, rv);
2448   EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2449 
2450   response = trans->GetResponseInfo();
2451   EXPECT_FALSE(response == NULL);
2452 
2453   // There is no challenge info, since the identity worked.
2454   EXPECT_TRUE(response->auth_challenge.get() == NULL);
2455 
2456   EXPECT_EQ(100, response->headers->GetContentLength());
2457 
2458   // Empty the current queue.
2459   MessageLoop::current()->RunAllPending();
2460 }
2461 
2462 // Test that previously tried username/passwords for a realm get re-used.
TEST_F(HttpNetworkTransactionTest,BasicAuthCacheAndPreauth)2463 TEST_F(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
2464   SessionDependencies session_deps;
2465   scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
2466 
2467   // Transaction 1: authenticate (foo, bar) on MyRealm1
2468   {
2469     scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2470 
2471     HttpRequestInfo request;
2472     request.method = "GET";
2473     request.url = GURL("http://www.google.com/x/y/z");
2474     request.load_flags = 0;
2475 
2476     MockWrite data_writes1[] = {
2477       MockWrite("GET /x/y/z HTTP/1.1\r\n"
2478                 "Host: www.google.com\r\n"
2479                 "Connection: keep-alive\r\n\r\n"),
2480     };
2481 
2482     MockRead data_reads1[] = {
2483       MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2484       MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2485       MockRead("Content-Length: 10000\r\n\r\n"),
2486       MockRead(false, ERR_FAILED),
2487     };
2488 
2489     // Resend with authorization (username=foo, password=bar)
2490     MockWrite data_writes2[] = {
2491       MockWrite("GET /x/y/z HTTP/1.1\r\n"
2492                 "Host: www.google.com\r\n"
2493                 "Connection: keep-alive\r\n"
2494                 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2495     };
2496 
2497     // Sever accepts the authorization.
2498     MockRead data_reads2[] = {
2499       MockRead("HTTP/1.0 200 OK\r\n"),
2500       MockRead("Content-Length: 100\r\n\r\n"),
2501       MockRead(false, OK),
2502     };
2503 
2504     StaticSocketDataProvider data1(data_reads1, data_writes1);
2505     StaticSocketDataProvider data2(data_reads2, data_writes2);
2506     session_deps.socket_factory.AddSocketDataProvider(&data1);
2507     session_deps.socket_factory.AddSocketDataProvider(&data2);
2508 
2509     TestCompletionCallback callback1;
2510 
2511     int rv = trans->Start(&request, &callback1, NULL);
2512     EXPECT_EQ(ERR_IO_PENDING, rv);
2513 
2514     rv = callback1.WaitForResult();
2515     EXPECT_EQ(OK, rv);
2516 
2517     const HttpResponseInfo* response = trans->GetResponseInfo();
2518     EXPECT_FALSE(response == NULL);
2519 
2520     // The password prompt info should have been set in
2521     // response->auth_challenge.
2522     EXPECT_FALSE(response->auth_challenge.get() == NULL);
2523 
2524     EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
2525     EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2526     EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2527 
2528     TestCompletionCallback callback2;
2529 
2530     rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
2531     EXPECT_EQ(ERR_IO_PENDING, rv);
2532 
2533     rv = callback2.WaitForResult();
2534     EXPECT_EQ(OK, rv);
2535 
2536     response = trans->GetResponseInfo();
2537     EXPECT_FALSE(response == NULL);
2538     EXPECT_TRUE(response->auth_challenge.get() == NULL);
2539     EXPECT_EQ(100, response->headers->GetContentLength());
2540   }
2541 
2542   // ------------------------------------------------------------------------
2543 
2544   // Transaction 2: authenticate (foo2, bar2) on MyRealm2
2545   {
2546     scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2547 
2548     HttpRequestInfo request;
2549     request.method = "GET";
2550     // Note that Transaction 1 was at /x/y/z, so this is in the same
2551     // protection space as MyRealm1.
2552     request.url = GURL("http://www.google.com/x/y/a/b");
2553     request.load_flags = 0;
2554 
2555     MockWrite data_writes1[] = {
2556       MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
2557                 "Host: www.google.com\r\n"
2558                 "Connection: keep-alive\r\n"
2559                 // Send preemptive authorization for MyRealm1
2560                 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2561     };
2562 
2563     // The server didn't like the preemptive authorization, and
2564     // challenges us for a different realm (MyRealm2).
2565     MockRead data_reads1[] = {
2566       MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2567       MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
2568       MockRead("Content-Length: 10000\r\n\r\n"),
2569       MockRead(false, ERR_FAILED),
2570     };
2571 
2572     // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
2573     MockWrite data_writes2[] = {
2574       MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
2575                 "Host: www.google.com\r\n"
2576                 "Connection: keep-alive\r\n"
2577                 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
2578     };
2579 
2580     // Sever accepts the authorization.
2581     MockRead data_reads2[] = {
2582       MockRead("HTTP/1.0 200 OK\r\n"),
2583       MockRead("Content-Length: 100\r\n\r\n"),
2584       MockRead(false, OK),
2585     };
2586 
2587     StaticSocketDataProvider data1(data_reads1, data_writes1);
2588     StaticSocketDataProvider data2(data_reads2, data_writes2);
2589     session_deps.socket_factory.AddSocketDataProvider(&data1);
2590     session_deps.socket_factory.AddSocketDataProvider(&data2);
2591 
2592     TestCompletionCallback callback1;
2593 
2594     int rv = trans->Start(&request, &callback1, NULL);
2595     EXPECT_EQ(ERR_IO_PENDING, rv);
2596 
2597     rv = callback1.WaitForResult();
2598     EXPECT_EQ(OK, rv);
2599 
2600     const HttpResponseInfo* response = trans->GetResponseInfo();
2601     EXPECT_FALSE(response == NULL);
2602 
2603     // The password prompt info should have been set in
2604     // response->auth_challenge.
2605     EXPECT_FALSE(response->auth_challenge.get() == NULL);
2606 
2607     EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
2608     EXPECT_EQ(L"MyRealm2", response->auth_challenge->realm);
2609     EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2610 
2611     TestCompletionCallback callback2;
2612 
2613     rv = trans->RestartWithAuth(L"foo2", L"bar2", &callback2);
2614     EXPECT_EQ(ERR_IO_PENDING, rv);
2615 
2616     rv = callback2.WaitForResult();
2617     EXPECT_EQ(OK, rv);
2618 
2619     response = trans->GetResponseInfo();
2620     EXPECT_FALSE(response == NULL);
2621     EXPECT_TRUE(response->auth_challenge.get() == NULL);
2622     EXPECT_EQ(100, response->headers->GetContentLength());
2623   }
2624 
2625   // ------------------------------------------------------------------------
2626 
2627   // Transaction 3: Resend a request in MyRealm's protection space --
2628   // succeed with preemptive authorization.
2629   {
2630     scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2631 
2632     HttpRequestInfo request;
2633     request.method = "GET";
2634     request.url = GURL("http://www.google.com/x/y/z2");
2635     request.load_flags = 0;
2636 
2637     MockWrite data_writes1[] = {
2638       MockWrite("GET /x/y/z2 HTTP/1.1\r\n"
2639                 "Host: www.google.com\r\n"
2640                 "Connection: keep-alive\r\n"
2641                 // The authorization for MyRealm1 gets sent preemptively
2642                 // (since the url is in the same protection space)
2643                 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2644     };
2645 
2646     // Sever accepts the preemptive authorization
2647     MockRead data_reads1[] = {
2648       MockRead("HTTP/1.0 200 OK\r\n"),
2649       MockRead("Content-Length: 100\r\n\r\n"),
2650       MockRead(false, OK),
2651     };
2652 
2653     StaticSocketDataProvider data1(data_reads1, data_writes1);
2654     session_deps.socket_factory.AddSocketDataProvider(&data1);
2655 
2656     TestCompletionCallback callback1;
2657 
2658     int rv = trans->Start(&request, &callback1, NULL);
2659     EXPECT_EQ(ERR_IO_PENDING, rv);
2660 
2661     rv = callback1.WaitForResult();
2662     EXPECT_EQ(OK, rv);
2663 
2664     const HttpResponseInfo* response = trans->GetResponseInfo();
2665     EXPECT_FALSE(response == NULL);
2666 
2667     EXPECT_TRUE(response->auth_challenge.get() == NULL);
2668     EXPECT_EQ(100, response->headers->GetContentLength());
2669   }
2670 
2671   // ------------------------------------------------------------------------
2672 
2673   // Transaction 4: request another URL in MyRealm (however the
2674   // url is not known to belong to the protection space, so no pre-auth).
2675   {
2676     scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2677 
2678     HttpRequestInfo request;
2679     request.method = "GET";
2680     request.url = GURL("http://www.google.com/x/1");
2681     request.load_flags = 0;
2682 
2683     MockWrite data_writes1[] = {
2684       MockWrite("GET /x/1 HTTP/1.1\r\n"
2685                 "Host: www.google.com\r\n"
2686                 "Connection: keep-alive\r\n\r\n"),
2687     };
2688 
2689     MockRead data_reads1[] = {
2690       MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2691       MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2692       MockRead("Content-Length: 10000\r\n\r\n"),
2693       MockRead(false, ERR_FAILED),
2694     };
2695 
2696     // Resend with authorization from MyRealm's cache.
2697     MockWrite data_writes2[] = {
2698       MockWrite("GET /x/1 HTTP/1.1\r\n"
2699                 "Host: www.google.com\r\n"
2700                 "Connection: keep-alive\r\n"
2701                 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2702     };
2703 
2704     // Sever accepts the authorization.
2705     MockRead data_reads2[] = {
2706       MockRead("HTTP/1.0 200 OK\r\n"),
2707       MockRead("Content-Length: 100\r\n\r\n"),
2708       MockRead(false, OK),
2709     };
2710 
2711     StaticSocketDataProvider data1(data_reads1, data_writes1);
2712     StaticSocketDataProvider data2(data_reads2, data_writes2);
2713     session_deps.socket_factory.AddSocketDataProvider(&data1);
2714     session_deps.socket_factory.AddSocketDataProvider(&data2);
2715 
2716     TestCompletionCallback callback1;
2717 
2718     int rv = trans->Start(&request, &callback1, NULL);
2719     EXPECT_EQ(ERR_IO_PENDING, rv);
2720 
2721     rv = callback1.WaitForResult();
2722     EXPECT_EQ(OK, rv);
2723 
2724     EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2725     TestCompletionCallback callback2;
2726     rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
2727     EXPECT_EQ(ERR_IO_PENDING, rv);
2728     rv = callback2.WaitForResult();
2729     EXPECT_EQ(OK, rv);
2730     EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2731 
2732     const HttpResponseInfo* response = trans->GetResponseInfo();
2733     EXPECT_FALSE(response == NULL);
2734     EXPECT_TRUE(response->auth_challenge.get() == NULL);
2735     EXPECT_EQ(100, response->headers->GetContentLength());
2736   }
2737 
2738   // ------------------------------------------------------------------------
2739 
2740   // Transaction 5: request a URL in MyRealm, but the server rejects the
2741   // cached identity. Should invalidate and re-prompt.
2742   {
2743     scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2744 
2745     HttpRequestInfo request;
2746     request.method = "GET";
2747     request.url = GURL("http://www.google.com/p/q/t");
2748     request.load_flags = 0;
2749 
2750     MockWrite data_writes1[] = {
2751       MockWrite("GET /p/q/t HTTP/1.1\r\n"
2752                 "Host: www.google.com\r\n"
2753                 "Connection: keep-alive\r\n\r\n"),
2754     };
2755 
2756     MockRead data_reads1[] = {
2757       MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2758       MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2759       MockRead("Content-Length: 10000\r\n\r\n"),
2760       MockRead(false, ERR_FAILED),
2761     };
2762 
2763     // Resend with authorization from cache for MyRealm.
2764     MockWrite data_writes2[] = {
2765       MockWrite("GET /p/q/t HTTP/1.1\r\n"
2766                 "Host: www.google.com\r\n"
2767                 "Connection: keep-alive\r\n"
2768                 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2769     };
2770 
2771     // Sever rejects the authorization.
2772     MockRead data_reads2[] = {
2773       MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2774       MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2775       MockRead("Content-Length: 10000\r\n\r\n"),
2776       MockRead(false, ERR_FAILED),
2777     };
2778 
2779     // At this point we should prompt for new credentials for MyRealm.
2780     // Restart with username=foo3, password=foo4.
2781     MockWrite data_writes3[] = {
2782       MockWrite("GET /p/q/t HTTP/1.1\r\n"
2783                 "Host: www.google.com\r\n"
2784                 "Connection: keep-alive\r\n"
2785                 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
2786     };
2787 
2788     // Sever accepts the authorization.
2789     MockRead data_reads3[] = {
2790       MockRead("HTTP/1.0 200 OK\r\n"),
2791       MockRead("Content-Length: 100\r\n\r\n"),
2792       MockRead(false, OK),
2793     };
2794 
2795     StaticSocketDataProvider data1(data_reads1, data_writes1);
2796     StaticSocketDataProvider data2(data_reads2, data_writes2);
2797     StaticSocketDataProvider data3(data_reads3, data_writes3);
2798     session_deps.socket_factory.AddSocketDataProvider(&data1);
2799     session_deps.socket_factory.AddSocketDataProvider(&data2);
2800     session_deps.socket_factory.AddSocketDataProvider(&data3);
2801 
2802     TestCompletionCallback callback1;
2803 
2804     int rv = trans->Start(&request, &callback1, NULL);
2805     EXPECT_EQ(ERR_IO_PENDING, rv);
2806 
2807     rv = callback1.WaitForResult();
2808     EXPECT_EQ(OK, rv);
2809 
2810     EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2811     TestCompletionCallback callback2;
2812     rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
2813     EXPECT_EQ(ERR_IO_PENDING, rv);
2814     rv = callback2.WaitForResult();
2815     EXPECT_EQ(OK, rv);
2816     EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2817 
2818     const HttpResponseInfo* response = trans->GetResponseInfo();
2819     EXPECT_FALSE(response == NULL);
2820 
2821     // The password prompt info should have been set in
2822     // response->auth_challenge.
2823     EXPECT_FALSE(response->auth_challenge.get() == NULL);
2824 
2825     EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
2826     EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2827     EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2828 
2829     TestCompletionCallback callback3;
2830 
2831     rv = trans->RestartWithAuth(L"foo3", L"bar3", &callback3);
2832     EXPECT_EQ(ERR_IO_PENDING, rv);
2833 
2834     rv = callback3.WaitForResult();
2835     EXPECT_EQ(OK, rv);
2836 
2837     response = trans->GetResponseInfo();
2838     EXPECT_FALSE(response == NULL);
2839     EXPECT_TRUE(response->auth_challenge.get() == NULL);
2840     EXPECT_EQ(100, response->headers->GetContentLength());
2841   }
2842 }
2843 
2844 // Test the ResetStateForRestart() private method.
TEST_F(HttpNetworkTransactionTest,ResetStateForRestart)2845 TEST_F(HttpNetworkTransactionTest, ResetStateForRestart) {
2846   // Create a transaction (the dependencies aren't important).
2847   SessionDependencies session_deps;
2848   scoped_ptr<HttpNetworkTransaction> trans(
2849       new HttpNetworkTransaction(CreateSession(&session_deps)));
2850 
2851   // Setup some state (which we expect ResetStateForRestart() will clear).
2852   trans->read_buf_ = new IOBuffer(15);
2853   trans->read_buf_len_ = 15;
2854   trans->request_headers_ = "Authorization: NTLM";
2855 
2856   // Setup state in response_
2857   HttpResponseInfo* response = &trans->response_;
2858   response->auth_challenge = new AuthChallengeInfo();
2859   response->ssl_info.cert_status = -15;
2860   response->response_time = base::Time::Now();
2861   response->was_cached = true;  // (Wouldn't ever actually be true...)
2862 
2863   { // Setup state for response_.vary_data
2864     HttpRequestInfo request;
2865     std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
2866     std::replace(temp.begin(), temp.end(), '\n', '\0');
2867     scoped_refptr<HttpResponseHeaders> headers = new HttpResponseHeaders(temp);
2868     request.extra_headers = "Foo: 1\nbar: 23";
2869     EXPECT_TRUE(response->vary_data.Init(request, *headers));
2870   }
2871 
2872   // Cause the above state to be reset.
2873   trans->ResetStateForRestart();
2874 
2875   // Verify that the state that needed to be reset, has been reset.
2876   EXPECT_TRUE(trans->read_buf_.get() == NULL);
2877   EXPECT_EQ(0, trans->read_buf_len_);
2878   EXPECT_EQ(0U, trans->request_headers_.size());
2879   EXPECT_TRUE(response->auth_challenge.get() == NULL);
2880   EXPECT_TRUE(response->headers.get() == NULL);
2881   EXPECT_EQ(false, response->was_cached);
2882   EXPECT_EQ(0, response->ssl_info.cert_status);
2883   EXPECT_FALSE(response->vary_data.is_valid());
2884 }
2885 
2886 // Test HTTPS connections to a site with a bad certificate
TEST_F(HttpNetworkTransactionTest,HTTPSBadCertificate)2887 TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificate) {
2888   SessionDependencies session_deps;
2889   scoped_ptr<HttpTransaction> trans(
2890       new HttpNetworkTransaction(CreateSession(&session_deps)));
2891 
2892   HttpRequestInfo request;
2893   request.method = "GET";
2894   request.url = GURL("https://www.google.com/");
2895   request.load_flags = 0;
2896 
2897   MockWrite data_writes[] = {
2898     MockWrite("GET / HTTP/1.1\r\n"
2899               "Host: www.google.com\r\n"
2900               "Connection: keep-alive\r\n\r\n"),
2901   };
2902 
2903   MockRead data_reads[] = {
2904     MockRead("HTTP/1.0 200 OK\r\n"),
2905     MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2906     MockRead("Content-Length: 100\r\n\r\n"),
2907     MockRead(false, OK),
2908   };
2909 
2910   StaticSocketDataProvider ssl_bad_certificate;
2911   StaticSocketDataProvider data(data_reads, data_writes);
2912   SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
2913   SSLSocketDataProvider ssl(true, OK);
2914 
2915   session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
2916   session_deps.socket_factory.AddSocketDataProvider(&data);
2917   session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
2918   session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2919 
2920   TestCompletionCallback callback;
2921 
2922   int rv = trans->Start(&request, &callback, NULL);
2923   EXPECT_EQ(ERR_IO_PENDING, rv);
2924 
2925   rv = callback.WaitForResult();
2926   EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
2927 
2928   rv = trans->RestartIgnoringLastError(&callback);
2929   EXPECT_EQ(ERR_IO_PENDING, rv);
2930 
2931   rv = callback.WaitForResult();
2932   EXPECT_EQ(OK, rv);
2933 
2934   const HttpResponseInfo* response = trans->GetResponseInfo();
2935 
2936   EXPECT_FALSE(response == NULL);
2937   EXPECT_EQ(100, response->headers->GetContentLength());
2938 }
2939 
2940 // Test HTTPS connections to a site with a bad certificate, going through a
2941 // proxy
TEST_F(HttpNetworkTransactionTest,HTTPSBadCertificateViaProxy)2942 TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
2943   SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
2944 
2945   HttpRequestInfo request;
2946   request.method = "GET";
2947   request.url = GURL("https://www.google.com/");
2948   request.load_flags = 0;
2949 
2950   MockWrite proxy_writes[] = {
2951     MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2952               "Host: www.google.com\r\n"
2953               "Proxy-Connection: keep-alive\r\n\r\n"),
2954   };
2955 
2956   MockRead proxy_reads[] = {
2957     MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
2958     MockRead(false, OK)
2959   };
2960 
2961   MockWrite data_writes[] = {
2962     MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2963               "Host: www.google.com\r\n"
2964               "Proxy-Connection: keep-alive\r\n\r\n"),
2965     MockWrite("GET / HTTP/1.1\r\n"
2966               "Host: www.google.com\r\n"
2967               "Connection: keep-alive\r\n\r\n"),
2968   };
2969 
2970   MockRead data_reads[] = {
2971     MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
2972     MockRead("HTTP/1.0 200 OK\r\n"),
2973     MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2974     MockRead("Content-Length: 100\r\n\r\n"),
2975     MockRead(false, OK),
2976   };
2977 
2978   StaticSocketDataProvider ssl_bad_certificate(proxy_reads, proxy_writes);
2979   StaticSocketDataProvider data(data_reads, data_writes);
2980   SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
2981   SSLSocketDataProvider ssl(true, OK);
2982 
2983   session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
2984   session_deps.socket_factory.AddSocketDataProvider(&data);
2985   session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
2986   session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2987 
2988   TestCompletionCallback callback;
2989 
2990   for (int i = 0; i < 2; i++) {
2991     session_deps.socket_factory.ResetNextMockIndexes();
2992 
2993     scoped_ptr<HttpTransaction> trans(
2994         new HttpNetworkTransaction(CreateSession(&session_deps)));
2995 
2996     int rv = trans->Start(&request, &callback, NULL);
2997     EXPECT_EQ(ERR_IO_PENDING, rv);
2998 
2999     rv = callback.WaitForResult();
3000     EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
3001 
3002     rv = trans->RestartIgnoringLastError(&callback);
3003     EXPECT_EQ(ERR_IO_PENDING, rv);
3004 
3005     rv = callback.WaitForResult();
3006     EXPECT_EQ(OK, rv);
3007 
3008     const HttpResponseInfo* response = trans->GetResponseInfo();
3009 
3010     EXPECT_FALSE(response == NULL);
3011     EXPECT_EQ(100, response->headers->GetContentLength());
3012   }
3013 }
3014 
TEST_F(HttpNetworkTransactionTest,BuildRequest_UserAgent)3015 TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
3016   SessionDependencies session_deps;
3017   scoped_ptr<HttpTransaction> trans(
3018       new HttpNetworkTransaction(CreateSession(&session_deps)));
3019 
3020   HttpRequestInfo request;
3021   request.method = "GET";
3022   request.url = GURL("http://www.google.com/");
3023   request.user_agent = "Chromium Ultra Awesome X Edition";
3024 
3025   MockWrite data_writes[] = {
3026     MockWrite("GET / HTTP/1.1\r\n"
3027               "Host: www.google.com\r\n"
3028               "Connection: keep-alive\r\n"
3029               "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
3030   };
3031 
3032   // Lastly, the server responds with the actual content.
3033   MockRead data_reads[] = {
3034     MockRead("HTTP/1.0 200 OK\r\n"),
3035     MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3036     MockRead("Content-Length: 100\r\n\r\n"),
3037     MockRead(false, OK),
3038   };
3039 
3040   StaticSocketDataProvider data(data_reads, data_writes);
3041   session_deps.socket_factory.AddSocketDataProvider(&data);
3042 
3043   TestCompletionCallback callback;
3044 
3045   int rv = trans->Start(&request, &callback, NULL);
3046   EXPECT_EQ(ERR_IO_PENDING, rv);
3047 
3048   rv = callback.WaitForResult();
3049   EXPECT_EQ(OK, rv);
3050 }
3051 
TEST_F(HttpNetworkTransactionTest,BuildRequest_Referer)3052 TEST_F(HttpNetworkTransactionTest, BuildRequest_Referer) {
3053   SessionDependencies session_deps;
3054   scoped_ptr<HttpTransaction> trans(
3055       new HttpNetworkTransaction(CreateSession(&session_deps)));
3056 
3057   HttpRequestInfo request;
3058   request.method = "GET";
3059   request.url = GURL("http://www.google.com/");
3060   request.load_flags = 0;
3061   request.referrer = GURL("http://the.previous.site.com/");
3062 
3063   MockWrite data_writes[] = {
3064     MockWrite("GET / HTTP/1.1\r\n"
3065               "Host: www.google.com\r\n"
3066               "Connection: keep-alive\r\n"
3067               "Referer: http://the.previous.site.com/\r\n\r\n"),
3068   };
3069 
3070   // Lastly, the server responds with the actual content.
3071   MockRead data_reads[] = {
3072     MockRead("HTTP/1.0 200 OK\r\n"),
3073     MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3074     MockRead("Content-Length: 100\r\n\r\n"),
3075     MockRead(false, OK),
3076   };
3077 
3078   StaticSocketDataProvider data(data_reads, data_writes);
3079   session_deps.socket_factory.AddSocketDataProvider(&data);
3080 
3081   TestCompletionCallback callback;
3082 
3083   int rv = trans->Start(&request, &callback, NULL);
3084   EXPECT_EQ(ERR_IO_PENDING, rv);
3085 
3086   rv = callback.WaitForResult();
3087   EXPECT_EQ(OK, rv);
3088 }
3089 
TEST_F(HttpNetworkTransactionTest,BuildRequest_PostContentLengthZero)3090 TEST_F(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
3091   SessionDependencies session_deps;
3092   scoped_ptr<HttpTransaction> trans(
3093       new HttpNetworkTransaction(CreateSession(&session_deps)));
3094 
3095   HttpRequestInfo request;
3096   request.method = "POST";
3097   request.url = GURL("http://www.google.com/");
3098 
3099   MockWrite data_writes[] = {
3100     MockWrite("POST / HTTP/1.1\r\n"
3101               "Host: www.google.com\r\n"
3102               "Connection: keep-alive\r\n"
3103               "Content-Length: 0\r\n\r\n"),
3104   };
3105 
3106   // Lastly, the server responds with the actual content.
3107   MockRead data_reads[] = {
3108     MockRead("HTTP/1.0 200 OK\r\n"),
3109     MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3110     MockRead("Content-Length: 100\r\n\r\n"),
3111     MockRead(false, OK),
3112   };
3113 
3114   StaticSocketDataProvider data(data_reads, data_writes);
3115   session_deps.socket_factory.AddSocketDataProvider(&data);
3116 
3117   TestCompletionCallback callback;
3118 
3119   int rv = trans->Start(&request, &callback, NULL);
3120   EXPECT_EQ(ERR_IO_PENDING, rv);
3121 
3122   rv = callback.WaitForResult();
3123   EXPECT_EQ(OK, rv);
3124 }
3125 
TEST_F(HttpNetworkTransactionTest,BuildRequest_PutContentLengthZero)3126 TEST_F(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
3127   SessionDependencies session_deps;
3128   scoped_ptr<HttpTransaction> trans(
3129       new HttpNetworkTransaction(CreateSession(&session_deps)));
3130 
3131   HttpRequestInfo request;
3132   request.method = "PUT";
3133   request.url = GURL("http://www.google.com/");
3134 
3135   MockWrite data_writes[] = {
3136     MockWrite("PUT / HTTP/1.1\r\n"
3137               "Host: www.google.com\r\n"
3138               "Connection: keep-alive\r\n"
3139               "Content-Length: 0\r\n\r\n"),
3140   };
3141 
3142   // Lastly, the server responds with the actual content.
3143   MockRead data_reads[] = {
3144     MockRead("HTTP/1.0 200 OK\r\n"),
3145     MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3146     MockRead("Content-Length: 100\r\n\r\n"),
3147     MockRead(false, OK),
3148   };
3149 
3150   StaticSocketDataProvider data(data_reads, data_writes);
3151   session_deps.socket_factory.AddSocketDataProvider(&data);
3152 
3153   TestCompletionCallback callback;
3154 
3155   int rv = trans->Start(&request, &callback, NULL);
3156   EXPECT_EQ(ERR_IO_PENDING, rv);
3157 
3158   rv = callback.WaitForResult();
3159   EXPECT_EQ(OK, rv);
3160 }
3161 
TEST_F(HttpNetworkTransactionTest,BuildRequest_HeadContentLengthZero)3162 TEST_F(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
3163   SessionDependencies session_deps;
3164   scoped_ptr<HttpTransaction> trans(
3165       new HttpNetworkTransaction(CreateSession(&session_deps)));
3166 
3167   HttpRequestInfo request;
3168   request.method = "HEAD";
3169   request.url = GURL("http://www.google.com/");
3170 
3171   MockWrite data_writes[] = {
3172     MockWrite("HEAD / HTTP/1.1\r\n"
3173               "Host: www.google.com\r\n"
3174               "Connection: keep-alive\r\n"
3175               "Content-Length: 0\r\n\r\n"),
3176   };
3177 
3178   // Lastly, the server responds with the actual content.
3179   MockRead data_reads[] = {
3180     MockRead("HTTP/1.0 200 OK\r\n"),
3181     MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3182     MockRead("Content-Length: 100\r\n\r\n"),
3183     MockRead(false, OK),
3184   };
3185 
3186   StaticSocketDataProvider data(data_reads, data_writes);
3187   session_deps.socket_factory.AddSocketDataProvider(&data);
3188 
3189   TestCompletionCallback callback;
3190 
3191   int rv = trans->Start(&request, &callback, NULL);
3192   EXPECT_EQ(ERR_IO_PENDING, rv);
3193 
3194   rv = callback.WaitForResult();
3195   EXPECT_EQ(OK, rv);
3196 }
3197 
TEST_F(HttpNetworkTransactionTest,BuildRequest_CacheControlNoCache)3198 TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
3199   SessionDependencies session_deps;
3200   scoped_ptr<HttpTransaction> trans(
3201       new HttpNetworkTransaction(CreateSession(&session_deps)));
3202 
3203   HttpRequestInfo request;
3204   request.method = "GET";
3205   request.url = GURL("http://www.google.com/");
3206   request.load_flags = LOAD_BYPASS_CACHE;
3207 
3208   MockWrite data_writes[] = {
3209     MockWrite("GET / HTTP/1.1\r\n"
3210               "Host: www.google.com\r\n"
3211               "Connection: keep-alive\r\n"
3212               "Pragma: no-cache\r\n"
3213               "Cache-Control: no-cache\r\n\r\n"),
3214   };
3215 
3216   // Lastly, the server responds with the actual content.
3217   MockRead data_reads[] = {
3218     MockRead("HTTP/1.0 200 OK\r\n"),
3219     MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3220     MockRead("Content-Length: 100\r\n\r\n"),
3221     MockRead(false, OK),
3222   };
3223 
3224   StaticSocketDataProvider data(data_reads, data_writes);
3225   session_deps.socket_factory.AddSocketDataProvider(&data);
3226 
3227   TestCompletionCallback callback;
3228 
3229   int rv = trans->Start(&request, &callback, NULL);
3230   EXPECT_EQ(ERR_IO_PENDING, rv);
3231 
3232   rv = callback.WaitForResult();
3233   EXPECT_EQ(OK, rv);
3234 }
3235 
TEST_F(HttpNetworkTransactionTest,BuildRequest_CacheControlValidateCache)3236 TEST_F(HttpNetworkTransactionTest,
3237        BuildRequest_CacheControlValidateCache) {
3238   SessionDependencies session_deps;
3239   scoped_ptr<HttpTransaction> trans(
3240       new HttpNetworkTransaction(CreateSession(&session_deps)));
3241 
3242   HttpRequestInfo request;
3243   request.method = "GET";
3244   request.url = GURL("http://www.google.com/");
3245   request.load_flags = LOAD_VALIDATE_CACHE;
3246 
3247   MockWrite data_writes[] = {
3248     MockWrite("GET / HTTP/1.1\r\n"
3249               "Host: www.google.com\r\n"
3250               "Connection: keep-alive\r\n"
3251               "Cache-Control: max-age=0\r\n\r\n"),
3252   };
3253 
3254   // Lastly, the server responds with the actual content.
3255   MockRead data_reads[] = {
3256     MockRead("HTTP/1.0 200 OK\r\n"),
3257     MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3258     MockRead("Content-Length: 100\r\n\r\n"),
3259     MockRead(false, OK),
3260   };
3261 
3262   StaticSocketDataProvider data(data_reads, data_writes);
3263   session_deps.socket_factory.AddSocketDataProvider(&data);
3264 
3265   TestCompletionCallback callback;
3266 
3267   int rv = trans->Start(&request, &callback, NULL);
3268   EXPECT_EQ(ERR_IO_PENDING, rv);
3269 
3270   rv = callback.WaitForResult();
3271   EXPECT_EQ(OK, rv);
3272 }
3273 
TEST_F(HttpNetworkTransactionTest,BuildRequest_ExtraHeaders)3274 TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
3275   SessionDependencies session_deps;
3276   scoped_ptr<HttpTransaction> trans(
3277       new HttpNetworkTransaction(CreateSession(&session_deps)));
3278 
3279   HttpRequestInfo request;
3280   request.method = "GET";
3281   request.url = GURL("http://www.google.com/");
3282   request.extra_headers = "FooHeader: Bar\r\n";
3283 
3284   MockWrite data_writes[] = {
3285     MockWrite("GET / HTTP/1.1\r\n"
3286               "Host: www.google.com\r\n"
3287               "Connection: keep-alive\r\n"
3288               "FooHeader: Bar\r\n\r\n"),
3289   };
3290 
3291   // Lastly, the server responds with the actual content.
3292   MockRead data_reads[] = {
3293     MockRead("HTTP/1.0 200 OK\r\n"),
3294     MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3295     MockRead("Content-Length: 100\r\n\r\n"),
3296     MockRead(false, OK),
3297   };
3298 
3299   StaticSocketDataProvider data(data_reads, data_writes);
3300   session_deps.socket_factory.AddSocketDataProvider(&data);
3301 
3302   TestCompletionCallback callback;
3303 
3304   int rv = trans->Start(&request, &callback, NULL);
3305   EXPECT_EQ(ERR_IO_PENDING, rv);
3306 
3307   rv = callback.WaitForResult();
3308   EXPECT_EQ(OK, rv);
3309 }
3310 
TEST_F(HttpNetworkTransactionTest,SOCKS4_HTTP_GET)3311 TEST_F(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
3312   SessionDependencies session_deps(
3313       CreateFixedProxyService("socks4://myproxy:1080"));
3314 
3315   scoped_ptr<HttpTransaction> trans(
3316       new HttpNetworkTransaction(CreateSession(&session_deps)));
3317 
3318   HttpRequestInfo request;
3319   request.method = "GET";
3320   request.url = GURL("http://www.google.com/");
3321   request.load_flags = 0;
3322 
3323   char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
3324   char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
3325 
3326   MockWrite data_writes[] = {
3327     MockWrite(true, write_buffer, arraysize(write_buffer)),
3328     MockWrite("GET / HTTP/1.1\r\n"
3329               "Host: www.google.com\r\n"
3330               "Connection: keep-alive\r\n\r\n")
3331   };
3332 
3333   MockRead data_reads[] = {
3334     MockRead(true, read_buffer, arraysize(read_buffer)),
3335     MockRead("HTTP/1.0 200 OK\r\n"),
3336     MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3337     MockRead("Payload"),
3338     MockRead(false, OK)
3339   };
3340 
3341   StaticSocketDataProvider data(data_reads, data_writes);
3342   session_deps.socket_factory.AddSocketDataProvider(&data);
3343 
3344   TestCompletionCallback callback;
3345 
3346   int rv = trans->Start(&request, &callback, NULL);
3347   EXPECT_EQ(ERR_IO_PENDING, rv);
3348 
3349   rv = callback.WaitForResult();
3350   EXPECT_EQ(OK, rv);
3351 
3352   const HttpResponseInfo* response = trans->GetResponseInfo();
3353   EXPECT_FALSE(response == NULL);
3354 
3355   std::string response_text;
3356   rv = ReadTransaction(trans.get(), &response_text);
3357   EXPECT_EQ(OK, rv);
3358   EXPECT_EQ("Payload", response_text);
3359 }
3360 
TEST_F(HttpNetworkTransactionTest,SOCKS4_SSL_GET)3361 TEST_F(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
3362   SessionDependencies session_deps(
3363       CreateFixedProxyService("socks4://myproxy:1080"));
3364 
3365   scoped_ptr<HttpTransaction> trans(
3366       new HttpNetworkTransaction(CreateSession(&session_deps)));
3367 
3368   HttpRequestInfo request;
3369   request.method = "GET";
3370   request.url = GURL("https://www.google.com/");
3371   request.load_flags = 0;
3372 
3373   unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
3374   unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
3375 
3376   MockWrite data_writes[] = {
3377     MockWrite(true, reinterpret_cast<char*>(write_buffer),
3378               arraysize(write_buffer)),
3379     MockWrite("GET / HTTP/1.1\r\n"
3380               "Host: www.google.com\r\n"
3381               "Connection: keep-alive\r\n\r\n")
3382   };
3383 
3384   MockRead data_reads[] = {
3385     MockWrite(true, reinterpret_cast<char*>(read_buffer),
3386               arraysize(read_buffer)),
3387     MockRead("HTTP/1.0 200 OK\r\n"),
3388     MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3389     MockRead("Payload"),
3390     MockRead(false, OK)
3391   };
3392 
3393   StaticSocketDataProvider data(data_reads, data_writes);
3394   session_deps.socket_factory.AddSocketDataProvider(&data);
3395 
3396   SSLSocketDataProvider ssl(true, OK);
3397   session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
3398 
3399   TestCompletionCallback callback;
3400 
3401   int rv = trans->Start(&request, &callback, NULL);
3402   EXPECT_EQ(ERR_IO_PENDING, rv);
3403 
3404   rv = callback.WaitForResult();
3405   EXPECT_EQ(OK, rv);
3406 
3407   const HttpResponseInfo* response = trans->GetResponseInfo();
3408   EXPECT_FALSE(response == NULL);
3409 
3410   std::string response_text;
3411   rv = ReadTransaction(trans.get(), &response_text);
3412   EXPECT_EQ(OK, rv);
3413   EXPECT_EQ("Payload", response_text);
3414 }
3415 
TEST_F(HttpNetworkTransactionTest,SOCKS5_HTTP_GET)3416 TEST_F(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
3417   SessionDependencies session_deps(
3418       CreateFixedProxyService("socks5://myproxy:1080"));
3419 
3420   scoped_ptr<HttpTransaction> trans(
3421       new HttpNetworkTransaction(CreateSession(&session_deps)));
3422 
3423   HttpRequestInfo request;
3424   request.method = "GET";
3425   request.url = GURL("http://www.google.com/");
3426   request.load_flags = 0;
3427 
3428   const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
3429   const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
3430   const char kSOCKS5OkRequest[] = {
3431     0x05,  // Version
3432     0x01,  // Command (CONNECT)
3433     0x00,  // Reserved.
3434     0x03,  // Address type (DOMAINNAME).
3435     0x0E,  // Length of domain (14)
3436     // Domain string:
3437     'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
3438     0x00, 0x50,  // 16-bit port (80)
3439   };
3440   const char kSOCKS5OkResponse[] =
3441       { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
3442 
3443   MockWrite data_writes[] = {
3444     MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
3445     MockWrite(true, kSOCKS5OkRequest, arraysize(kSOCKS5OkRequest)),
3446     MockWrite("GET / HTTP/1.1\r\n"
3447               "Host: www.google.com\r\n"
3448               "Connection: keep-alive\r\n\r\n")
3449   };
3450 
3451   MockRead data_reads[] = {
3452     MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
3453     MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
3454     MockRead("HTTP/1.0 200 OK\r\n"),
3455     MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3456     MockRead("Payload"),
3457     MockRead(false, OK)
3458   };
3459 
3460   StaticSocketDataProvider data(data_reads, data_writes);
3461   session_deps.socket_factory.AddSocketDataProvider(&data);
3462 
3463   TestCompletionCallback callback;
3464 
3465   int rv = trans->Start(&request, &callback, NULL);
3466   EXPECT_EQ(ERR_IO_PENDING, rv);
3467 
3468   rv = callback.WaitForResult();
3469   EXPECT_EQ(OK, rv);
3470 
3471   const HttpResponseInfo* response = trans->GetResponseInfo();
3472   EXPECT_FALSE(response == NULL);
3473 
3474   std::string response_text;
3475   rv = ReadTransaction(trans.get(), &response_text);
3476   EXPECT_EQ(OK, rv);
3477   EXPECT_EQ("Payload", response_text);
3478 }
3479 
TEST_F(HttpNetworkTransactionTest,SOCKS5_SSL_GET)3480 TEST_F(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
3481   SessionDependencies session_deps(
3482       CreateFixedProxyService("socks5://myproxy:1080"));
3483 
3484   scoped_ptr<HttpTransaction> trans(
3485       new HttpNetworkTransaction(CreateSession(&session_deps)));
3486 
3487   HttpRequestInfo request;
3488   request.method = "GET";
3489   request.url = GURL("https://www.google.com/");
3490   request.load_flags = 0;
3491 
3492   const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
3493   const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
3494   const unsigned char kSOCKS5OkRequest[] = {
3495     0x05,  // Version
3496     0x01,  // Command (CONNECT)
3497     0x00,  // Reserved.
3498     0x03,  // Address type (DOMAINNAME).
3499     0x0E,  // Length of domain (14)
3500     // Domain string:
3501     'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
3502     0x01, 0xBB,  // 16-bit port (443)
3503   };
3504 
3505   const char kSOCKS5OkResponse[] =
3506       { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
3507 
3508   MockWrite data_writes[] = {
3509     MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
3510     MockWrite(true, reinterpret_cast<const char*>(kSOCKS5OkRequest),
3511               arraysize(kSOCKS5OkRequest)),
3512     MockWrite("GET / HTTP/1.1\r\n"
3513               "Host: www.google.com\r\n"
3514               "Connection: keep-alive\r\n\r\n")
3515   };
3516 
3517   MockRead data_reads[] = {
3518     MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
3519     MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
3520     MockRead("HTTP/1.0 200 OK\r\n"),
3521     MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3522     MockRead("Payload"),
3523     MockRead(false, OK)
3524   };
3525 
3526   StaticSocketDataProvider data(data_reads, data_writes);
3527   session_deps.socket_factory.AddSocketDataProvider(&data);
3528 
3529   SSLSocketDataProvider ssl(true, OK);
3530   session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
3531 
3532   TestCompletionCallback callback;
3533 
3534   int rv = trans->Start(&request, &callback, NULL);
3535   EXPECT_EQ(ERR_IO_PENDING, rv);
3536 
3537   rv = callback.WaitForResult();
3538   EXPECT_EQ(OK, rv);
3539 
3540   const HttpResponseInfo* response = trans->GetResponseInfo();
3541   EXPECT_FALSE(response == NULL);
3542 
3543   std::string response_text;
3544   rv = ReadTransaction(trans.get(), &response_text);
3545   EXPECT_EQ(OK, rv);
3546   EXPECT_EQ("Payload", response_text);
3547 }
3548 
3549 // Tests that for connection endpoints the group names are correctly set.
TEST_F(HttpNetworkTransactionTest,GroupNameForProxyConnections)3550 TEST_F(HttpNetworkTransactionTest, GroupNameForProxyConnections) {
3551   const struct {
3552     const std::string proxy_server;
3553     const std::string url;
3554     const std::string expected_group_name;
3555   } tests[] = {
3556     {
3557       "",  // no proxy (direct)
3558       "http://www.google.com/direct",
3559       "http://www.google.com/",
3560     },
3561     {
3562       "http_proxy",
3563       "http://www.google.com/http_proxy_normal",
3564       "proxy/http_proxy:80/",
3565     },
3566     {
3567       "socks4://socks_proxy:1080",
3568       "http://www.google.com/socks4_direct",
3569       "proxy/socks4://socks_proxy:1080/http://www.google.com/",
3570     },
3571 
3572     // SSL Tests
3573     {
3574       "",
3575       "https://www.google.com/direct_ssl",
3576       "https://www.google.com/",
3577     },
3578     {
3579       "http_proxy",
3580       "https://www.google.com/http_connect_ssl",
3581       "proxy/http_proxy:80/https://www.google.com/",
3582     },
3583     {
3584       "socks4://socks_proxy:1080",
3585       "https://www.google.com/socks4_ssl",
3586       "proxy/socks4://socks_proxy:1080/https://www.google.com/",
3587     },
3588   };
3589 
3590   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
3591     SessionDependencies session_deps(
3592         CreateFixedProxyService(tests[i].proxy_server));
3593 
3594     scoped_refptr<CaptureGroupNameSocketPool> conn_pool(
3595         new CaptureGroupNameSocketPool());
3596 
3597     scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
3598     session->tcp_socket_pool_ = conn_pool.get();
3599 
3600     scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3601 
3602     HttpRequestInfo request;
3603     request.method = "GET";
3604     request.url = GURL(tests[i].url);
3605     request.load_flags = 0;
3606 
3607     TestCompletionCallback callback;
3608 
3609     // We do not complete this request, the dtor will clean the transaction up.
3610     EXPECT_EQ(ERR_IO_PENDING, trans->Start(&request, &callback, NULL));
3611     EXPECT_EQ(tests[i].expected_group_name,
3612               conn_pool->last_group_name_received());
3613   }
3614 }
3615 
TEST_F(HttpNetworkTransactionTest,ReconsiderProxyAfterFailedConnection)3616 TEST_F(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
3617   SessionDependencies session_deps(
3618       CreateFixedProxyService("myproxy:70;foobar:80"));
3619 
3620   // This simulates failure resolving all hostnames; that means we will fail
3621   // connecting to both proxies (myproxy:70 and foobar:80).
3622   session_deps.host_resolver->rules()->AddSimulatedFailure("*");
3623 
3624   scoped_ptr<HttpTransaction> trans(
3625       new HttpNetworkTransaction(CreateSession(&session_deps)));
3626 
3627   HttpRequestInfo request;
3628   request.method = "GET";
3629   request.url = GURL("http://www.google.com/");
3630 
3631   TestCompletionCallback callback;
3632 
3633   int rv = trans->Start(&request, &callback, NULL);
3634   EXPECT_EQ(ERR_IO_PENDING, rv);
3635 
3636   rv = callback.WaitForResult();
3637   EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
3638 }
3639 
3640 // Host resolution observer used by
3641 // HttpNetworkTransactionTest.ResolveMadeWithReferrer to check that host
3642 // resovle requests are issued with a referrer of |expected_referrer|.
3643 class ResolutionReferrerObserver : public HostResolver::Observer {
3644  public:
ResolutionReferrerObserver(const GURL & expected_referrer)3645   explicit ResolutionReferrerObserver(const GURL& expected_referrer)
3646       : expected_referrer_(expected_referrer),
3647         called_start_with_referrer_(false),
3648         called_finish_with_referrer_(false) {
3649   }
3650 
OnStartResolution(int id,const HostResolver::RequestInfo & info)3651   virtual void OnStartResolution(int id,
3652                                  const HostResolver::RequestInfo& info) {
3653     if (info.referrer() == expected_referrer_)
3654       called_start_with_referrer_ = true;
3655   }
3656 
OnFinishResolutionWithStatus(int id,bool was_resolved,const HostResolver::RequestInfo & info)3657   virtual void OnFinishResolutionWithStatus(
3658       int id, bool was_resolved, const HostResolver::RequestInfo& info ) {
3659     if (info.referrer() == expected_referrer_)
3660       called_finish_with_referrer_ = true;
3661   }
3662 
OnCancelResolution(int id,const HostResolver::RequestInfo & info)3663   virtual void OnCancelResolution(int id,
3664                                   const HostResolver::RequestInfo& info ) {
3665     FAIL() << "Should not be cancelling any requests!";
3666   }
3667 
did_complete_with_expected_referrer() const3668   bool did_complete_with_expected_referrer() const {
3669     return called_start_with_referrer_ && called_finish_with_referrer_;
3670   }
3671 
3672  private:
3673   GURL expected_referrer_;
3674   bool called_start_with_referrer_;
3675   bool called_finish_with_referrer_;
3676 
3677   DISALLOW_COPY_AND_ASSIGN(ResolutionReferrerObserver);
3678 };
3679 
3680 // Make sure that when HostResolver::Resolve() is invoked, it passes through
3681 // the "referrer". This is depended on by the DNS prefetch observer.
TEST_F(HttpNetworkTransactionTest,ResolveMadeWithReferrer)3682 TEST_F(HttpNetworkTransactionTest, ResolveMadeWithReferrer) {
3683   GURL referrer = GURL("http://expected-referrer/");
3684   EXPECT_TRUE(referrer.is_valid());
3685   ResolutionReferrerObserver resolution_observer(referrer);
3686 
3687   SessionDependencies session_deps;
3688   scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
3689       CreateSession(&session_deps)));
3690 
3691   // Attach an observer to watch the host resolutions being made.
3692   session_deps.host_resolver->AddObserver(&resolution_observer);
3693 
3694   // Connect up a mock socket which will fail when reading.
3695   MockRead data_reads[] = {
3696     MockRead(false, ERR_FAILED),
3697   };
3698   StaticSocketDataProvider data(data_reads, NULL);
3699   session_deps.socket_factory.AddSocketDataProvider(&data);
3700 
3701   // Issue a request, containing an HTTP referrer.
3702   HttpRequestInfo request;
3703   request.method = "GET";
3704   request.referrer = referrer;
3705   request.url = GURL("http://www.google.com/");
3706 
3707   // Run the request until it fails reading from the socket.
3708   TestCompletionCallback callback;
3709   int rv = trans->Start(&request, &callback, NULL);
3710   EXPECT_EQ(ERR_IO_PENDING, rv);
3711   rv = callback.WaitForResult();
3712   EXPECT_EQ(ERR_FAILED, rv);
3713 
3714   // Check that the host resolution observer saw |referrer|.
3715   EXPECT_TRUE(resolution_observer.did_complete_with_expected_referrer());
3716 }
3717 
3718 // Make sure that when the load flags contain LOAD_BYPASS_CACHE, the resolver's
3719 // host cache is bypassed.
TEST_F(HttpNetworkTransactionTest,BypassHostCacheOnRefresh)3720 TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh) {
3721   SessionDependencies session_deps;
3722 
3723   // Select a host resolver that does caching.
3724   session_deps.host_resolver = new MockCachingHostResolver;
3725 
3726   scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
3727       CreateSession(&session_deps)));
3728 
3729   // Warm up the host cache so it has an entry for "www.google.com" (by doing
3730   // a synchronous lookup.)
3731   AddressList addrlist;
3732   int rv = session_deps.host_resolver->Resolve(
3733       HostResolver::RequestInfo("www.google.com", 80), &addrlist,
3734       NULL, NULL, NULL);
3735   EXPECT_EQ(OK, rv);
3736 
3737   // Verify that it was added to host cache, by doing a subsequent async lookup
3738   // and confirming it completes synchronously.
3739   TestCompletionCallback resolve_callback;
3740   rv = session_deps.host_resolver->Resolve(
3741       HostResolver::RequestInfo("www.google.com", 80), &addrlist,
3742       &resolve_callback, NULL, NULL);
3743   ASSERT_EQ(OK, rv);
3744 
3745   // Inject a failure the next time that "www.google.com" is resolved. This way
3746   // we can tell if the next lookup hit the cache, or the "network".
3747   // (cache --> success, "network" --> failure).
3748   session_deps.host_resolver->rules()->AddSimulatedFailure("www.google.com");
3749 
3750   // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
3751   // first read -- this won't be reached as the host resolution will fail first.
3752   MockRead data_reads[] = { MockRead(false, ERR_UNEXPECTED) };
3753   StaticSocketDataProvider data(data_reads, NULL);
3754   session_deps.socket_factory.AddSocketDataProvider(&data);
3755 
3756   // Issue a request, asking to bypass the cache(s).
3757   HttpRequestInfo request;
3758   request.method = "GET";
3759   request.load_flags = LOAD_BYPASS_CACHE;
3760   request.url = GURL("http://www.google.com/");
3761 
3762   // Run the request.
3763   TestCompletionCallback callback;
3764   rv = trans->Start(&request, &callback, NULL);
3765   ASSERT_EQ(ERR_IO_PENDING, rv);
3766   rv = callback.WaitForResult();
3767 
3768   // If we bypassed the cache, we would have gotten a failure while resolving
3769   // "www.google.com".
3770   EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
3771 }
3772 
3773 // Make sure we can handle an error when writing the request.
TEST_F(HttpNetworkTransactionTest,RequestWriteError)3774 TEST_F(HttpNetworkTransactionTest, RequestWriteError) {
3775   SessionDependencies session_deps;
3776   scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
3777 
3778   HttpRequestInfo request;
3779   request.method = "GET";
3780   request.url = GURL("http://www.foo.com/");
3781   request.load_flags = 0;
3782 
3783   MockWrite write_failure[] = {
3784     MockWrite(true, ERR_CONNECTION_RESET),
3785   };
3786   StaticSocketDataProvider data(NULL, write_failure);
3787   session_deps.socket_factory.AddSocketDataProvider(&data);
3788 
3789   TestCompletionCallback callback;
3790 
3791   scoped_ptr<HttpTransaction> trans(
3792       new HttpNetworkTransaction(CreateSession(&session_deps)));
3793 
3794   int rv = trans->Start(&request, &callback, NULL);
3795   EXPECT_EQ(ERR_IO_PENDING, rv);
3796 
3797   rv = callback.WaitForResult();
3798   EXPECT_EQ(ERR_CONNECTION_RESET, rv);
3799 }
3800 
3801 // Check that a connection closed after the start of the headers finishes ok.
TEST_F(HttpNetworkTransactionTest,ConnectionClosedAfterStartOfHeaders)3802 TEST_F(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
3803   SessionDependencies session_deps;
3804   scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
3805 
3806   HttpRequestInfo request;
3807   request.method = "GET";
3808   request.url = GURL("http://www.foo.com/");
3809   request.load_flags = 0;
3810 
3811   MockRead data_reads[] = {
3812     MockRead("HTTP/1."),
3813     MockRead(false, OK),
3814   };
3815 
3816   StaticSocketDataProvider data(data_reads, NULL);
3817   session_deps.socket_factory.AddSocketDataProvider(&data);
3818 
3819   TestCompletionCallback callback;
3820 
3821   scoped_ptr<HttpTransaction> trans(
3822       new HttpNetworkTransaction(CreateSession(&session_deps)));
3823 
3824   int rv = trans->Start(&request, &callback, NULL);
3825   EXPECT_EQ(ERR_IO_PENDING, rv);
3826 
3827   rv = callback.WaitForResult();
3828   EXPECT_EQ(OK, rv);
3829 
3830   const HttpResponseInfo* response = trans->GetResponseInfo();
3831   EXPECT_TRUE(response != NULL);
3832 
3833   EXPECT_TRUE(response->headers != NULL);
3834   EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
3835 
3836   std::string response_data;
3837   rv = ReadTransaction(trans.get(), &response_data);
3838   EXPECT_EQ(OK, rv);
3839   EXPECT_EQ("", response_data);
3840 }
3841 
3842 // Make sure that a dropped connection while draining the body for auth
3843 // restart does the right thing.
TEST_F(HttpNetworkTransactionTest,DrainResetOK)3844 TEST_F(HttpNetworkTransactionTest, DrainResetOK) {
3845   SessionDependencies session_deps;
3846   scoped_ptr<HttpTransaction> trans(
3847       new HttpNetworkTransaction(CreateSession(&session_deps)));
3848 
3849   HttpRequestInfo request;
3850   request.method = "GET";
3851   request.url = GURL("http://www.google.com/");
3852   request.load_flags = 0;
3853 
3854   MockWrite data_writes1[] = {
3855     MockWrite("GET / HTTP/1.1\r\n"
3856               "Host: www.google.com\r\n"
3857               "Connection: keep-alive\r\n\r\n"),
3858   };
3859 
3860   MockRead data_reads1[] = {
3861     MockRead("HTTP/1.1 401 Unauthorized\r\n"),
3862     MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3863     MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3864     MockRead("Content-Length: 14\r\n\r\n"),
3865     MockRead("Unauth"),
3866     MockRead(true, ERR_CONNECTION_RESET),
3867   };
3868 
3869   StaticSocketDataProvider data1(data_reads1, data_writes1);
3870   session_deps.socket_factory.AddSocketDataProvider(&data1);
3871 
3872   // After calling trans->RestartWithAuth(), this is the request we should
3873   // be issuing -- the final header line contains the credentials.
3874   MockWrite data_writes2[] = {
3875     MockWrite("GET / HTTP/1.1\r\n"
3876               "Host: www.google.com\r\n"
3877               "Connection: keep-alive\r\n"
3878               "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3879   };
3880 
3881   // Lastly, the server responds with the actual content.
3882   MockRead data_reads2[] = {
3883     MockRead("HTTP/1.1 200 OK\r\n"),
3884     MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3885     MockRead("Content-Length: 100\r\n\r\n"),
3886     MockRead(false, OK),
3887   };
3888 
3889   StaticSocketDataProvider data2(data_reads2, data_writes2);
3890   session_deps.socket_factory.AddSocketDataProvider(&data2);
3891 
3892   TestCompletionCallback callback1;
3893 
3894   int rv = trans->Start(&request, &callback1, NULL);
3895   EXPECT_EQ(ERR_IO_PENDING, rv);
3896 
3897   rv = callback1.WaitForResult();
3898   EXPECT_EQ(OK, rv);
3899 
3900   const HttpResponseInfo* response = trans->GetResponseInfo();
3901   EXPECT_FALSE(response == NULL);
3902 
3903   // The password prompt info should have been set in response->auth_challenge.
3904   EXPECT_FALSE(response->auth_challenge.get() == NULL);
3905 
3906   EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
3907   EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
3908   EXPECT_EQ(L"basic", response->auth_challenge->scheme);
3909 
3910   TestCompletionCallback callback2;
3911 
3912   rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
3913   EXPECT_EQ(ERR_IO_PENDING, rv);
3914 
3915   rv = callback2.WaitForResult();
3916   EXPECT_EQ(OK, rv);
3917 
3918   response = trans->GetResponseInfo();
3919   EXPECT_FALSE(response == NULL);
3920   EXPECT_TRUE(response->auth_challenge.get() == NULL);
3921   EXPECT_EQ(100, response->headers->GetContentLength());
3922 }
3923 
3924 // Test HTTPS connections going through a proxy that sends extra data.
TEST_F(HttpNetworkTransactionTest,HTTPSViaProxyWithExtraData)3925 TEST_F(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
3926   SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
3927 
3928   HttpRequestInfo request;
3929   request.method = "GET";
3930   request.url = GURL("https://www.google.com/");
3931   request.load_flags = 0;
3932 
3933   MockRead proxy_reads[] = {
3934     MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
3935     MockRead(false, OK)
3936   };
3937 
3938   StaticSocketDataProvider data(proxy_reads, NULL);
3939   SSLSocketDataProvider ssl(true, OK);
3940 
3941   session_deps.socket_factory.AddSocketDataProvider(&data);
3942   session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
3943 
3944   TestCompletionCallback callback;
3945 
3946   session_deps.socket_factory.ResetNextMockIndexes();
3947 
3948   scoped_ptr<HttpTransaction> trans(
3949       new HttpNetworkTransaction(CreateSession(&session_deps)));
3950 
3951   int rv = trans->Start(&request, &callback, NULL);
3952   EXPECT_EQ(ERR_IO_PENDING, rv);
3953 
3954   rv = callback.WaitForResult();
3955   EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
3956 }
3957 
TEST_F(HttpNetworkTransactionTest,LargeContentLengthThenClose)3958 TEST_F(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
3959   MockRead data_reads[] = {
3960     MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
3961     MockRead(false, OK),
3962   };
3963   SimpleGetHelperResult out = SimpleGetHelper(data_reads);
3964   EXPECT_EQ(OK, out.rv);
3965   EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
3966   EXPECT_EQ("", out.response_data);
3967 }
3968 
3969 }  // namespace net
3970