Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / net / http / http_network_layer_unittest.cc
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "net/http/http_network_layer.h"
6
7 #include "base/basictypes.h"
8 #include "base/strings/stringprintf.h"
9 #include "net/base/net_log.h"
10 #include "net/cert/mock_cert_verifier.h"
11 #include "net/dns/mock_host_resolver.h"
12 #include "net/http/http_network_session.h"
13 #include "net/http/http_server_properties_impl.h"
14 #include "net/http/http_transaction_unittest.h"
15 #include "net/http/transport_security_state.h"
16 #include "net/proxy/proxy_service.h"
17 #include "net/socket/socket_test_util.h"
18 #include "net/spdy/spdy_session_pool.h"
19 #include "net/ssl/ssl_config_service_defaults.h"
20 #include "testing/gtest/include/gtest/gtest.h"
21 #include "testing/platform_test.h"
22
23 namespace net {
24
25 namespace {
26
27 class HttpNetworkLayerTest : public PlatformTest {
28  protected:
29   HttpNetworkLayerTest() : ssl_config_service_(new SSLConfigServiceDefaults) {}
30
31   virtual void SetUp() {
32     ConfigureTestDependencies(ProxyService::CreateDirect());
33   }
34
35   void ConfigureTestDependencies(ProxyService* proxy_service) {
36     cert_verifier_.reset(new MockCertVerifier);
37     transport_security_state_.reset(new TransportSecurityState);
38     proxy_service_.reset(proxy_service);
39     HttpNetworkSession::Params session_params;
40     session_params.client_socket_factory = &mock_socket_factory_;
41     session_params.host_resolver = &host_resolver_;
42     session_params.cert_verifier = cert_verifier_.get();
43     session_params.transport_security_state = transport_security_state_.get();
44     session_params.proxy_service = proxy_service_.get();
45     session_params.ssl_config_service = ssl_config_service_.get();
46     session_params.http_server_properties =
47         http_server_properties_.GetWeakPtr();
48     network_session_ = new HttpNetworkSession(session_params);
49     factory_.reset(new HttpNetworkLayer(network_session_.get()));
50   }
51
52 #if defined(SPDY_PROXY_AUTH_ORIGIN)
53   std::string GetChromeProxy() {
54     return HostPortPair::FromURL(GURL(SPDY_PROXY_AUTH_ORIGIN)).ToString();
55   }
56 #endif
57
58 #if defined(SPDY_PROXY_AUTH_ORIGIN) && defined(DATA_REDUCTION_FALLBACK_HOST)
59   std::string GetChromeFallbackProxy() {
60     return HostPortPair::FromURL(GURL(DATA_REDUCTION_FALLBACK_HOST)).ToString();
61   }
62 #endif
63
64   void ExecuteRequestExpectingContentAndHeader(const std::string& method,
65                                                const std::string& content,
66                                                const std::string& header,
67                                                const std::string& value) {
68     TestCompletionCallback callback;
69
70     HttpRequestInfo request_info;
71     request_info.url = GURL("http://www.google.com/");
72     request_info.method = method;
73     request_info.load_flags = LOAD_NORMAL;
74
75     scoped_ptr<HttpTransaction> trans;
76     int rv = factory_->CreateTransaction(DEFAULT_PRIORITY, &trans);
77     EXPECT_EQ(OK, rv);
78
79     rv = trans->Start(&request_info, callback.callback(), BoundNetLog());
80     if (rv == ERR_IO_PENDING)
81       rv = callback.WaitForResult();
82     ASSERT_EQ(OK, rv);
83
84     std::string contents;
85     rv = ReadTransaction(trans.get(), &contents);
86     EXPECT_EQ(OK, rv);
87     EXPECT_EQ(content, contents);
88
89     if (!header.empty()) {
90       // We also have a server header here that isn't set by the proxy.
91       EXPECT_TRUE(trans->GetResponseInfo()->headers->HasHeaderValue(
92           header, value));
93     }
94   }
95
96   // Check that |proxy_count| proxies are in the retry list.
97   // These will be, in order, |bad_proxy| and |bad_proxy2|".
98   void TestBadProxies(unsigned int proxy_count, const std::string& bad_proxy,
99                       const std::string& bad_proxy2) {
100     const ProxyRetryInfoMap& retry_info = proxy_service_->proxy_retry_info();
101     ASSERT_EQ(proxy_count, retry_info.size());
102     if (proxy_count > 0)
103       ASSERT_TRUE(retry_info.find(bad_proxy) != retry_info.end());
104     if (proxy_count > 1)
105       ASSERT_TRUE(retry_info.find(bad_proxy2) != retry_info.end());
106   }
107
108   // Simulates a request through a proxy which returns a bypass, which is then
109   // retried through a second proxy that doesn't bypass.
110   // Checks that the expected requests were issued, the expected content was
111   // recieved, and the first proxy |bad_proxy| was marked as bad.
112   void TestProxyFallback(const std::string& bad_proxy) {
113     MockRead data_reads[] = {
114       MockRead("HTTP/1.1 200 OK\r\n"
115                "Chrome-Proxy: bypass=0\r\n\r\n"),
116       MockRead("Bypass message"),
117       MockRead(SYNCHRONOUS, OK),
118     };
119     TestProxyFallbackWithMockReads(bad_proxy, "", data_reads,
120                                    arraysize(data_reads), 1u);
121   }
122
123   void TestProxyFallbackWithMockReads(const std::string& bad_proxy,
124                                       const std::string& bad_proxy2,
125                                       MockRead data_reads[],
126                                       int data_reads_size,
127                                       unsigned int expected_retry_info_size) {
128     TestProxyFallbackByMethodWithMockReads(bad_proxy, bad_proxy2, data_reads,
129                                            data_reads_size, "GET", "content",
130                                            true, expected_retry_info_size);
131   }
132
133   void TestProxyFallbackByMethodWithMockReads(
134       const std::string& bad_proxy,
135       const std::string& bad_proxy2,
136       MockRead data_reads[],
137       int data_reads_size,
138       std::string method,
139       std::string content,
140       bool retry_expected,
141       unsigned int expected_retry_info_size) {
142     std::string trailer =
143         (method == "HEAD" || method == "PUT" || method == "POST") ?
144         "Content-Length: 0\r\n\r\n" : "\r\n";
145     std::string request =
146         base::StringPrintf("%s http://www.google.com/ HTTP/1.1\r\n"
147                            "Host: www.google.com\r\n"
148                            "Proxy-Connection: keep-alive\r\n"
149                            "%s", method.c_str(), trailer.c_str());
150
151     MockWrite data_writes[] = {
152       MockWrite(request.c_str()),
153     };
154
155     StaticSocketDataProvider data1(data_reads, data_reads_size,
156                                   data_writes, arraysize(data_writes));
157     mock_socket_factory_.AddSocketDataProvider(&data1);
158
159     // Second data provider returns the expected content.
160     MockRead data_reads2[3];
161     size_t data_reads2_index = 0;
162     data_reads2[data_reads2_index++] = MockRead("HTTP/1.0 200 OK\r\n"
163                                                 "Server: not-proxy\r\n\r\n");
164     if (!content.empty())
165       data_reads2[data_reads2_index++] = MockRead(content.c_str());
166     data_reads2[data_reads2_index++] = MockRead(SYNCHRONOUS, OK);
167
168     MockWrite data_writes2[] = {
169       MockWrite(request.c_str()),
170     };
171     StaticSocketDataProvider data2(data_reads2, data_reads2_index,
172                                   data_writes2, arraysize(data_writes2));
173     mock_socket_factory_.AddSocketDataProvider(&data2);
174
175     // Expect that we get "content" and not "Bypass message", and that there's
176     // a "not-proxy" "Server:" header in the final response.
177     if (retry_expected) {
178       ExecuteRequestExpectingContentAndHeader(method, content,
179                                               "server", "not-proxy");
180     } else {
181       ExecuteRequestExpectingContentAndHeader(method, content, "", "");
182     }
183
184     // We should also observe the bad proxy in the retry list.
185     TestBadProxies(expected_retry_info_size, bad_proxy, bad_proxy2);
186   }
187
188   // Simulates a request through a proxy which returns a bypass, which is then
189   // retried through a direct connection to the origin site.
190   // Checks that the expected requests were issued, the expected content was
191   // received, and the proxy |bad_proxy| was marked as bad.
192   void TestProxyFallbackToDirect(const std::string& bad_proxy) {
193     MockRead data_reads[] = {
194       MockRead("HTTP/1.1 200 OK\r\n"
195                "Chrome-Proxy: bypass=0\r\n\r\n"),
196       MockRead("Bypass message"),
197       MockRead(SYNCHRONOUS, OK),
198     };
199     MockWrite data_writes[] = {
200       MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
201                 "Host: www.google.com\r\n"
202                 "Proxy-Connection: keep-alive\r\n\r\n"),
203     };
204     StaticSocketDataProvider data1(data_reads, arraysize(data_reads),
205                                   data_writes, arraysize(data_writes));
206     mock_socket_factory_.AddSocketDataProvider(&data1);
207
208     // Second data provider returns the expected content.
209     MockRead data_reads2[] = {
210       MockRead("HTTP/1.0 200 OK\r\n"
211                "Server: not-proxy\r\n\r\n"),
212       MockRead("content"),
213       MockRead(SYNCHRONOUS, OK),
214     };
215     MockWrite data_writes2[] = {
216       MockWrite("GET / HTTP/1.1\r\n"
217                 "Host: www.google.com\r\n"
218                 "Connection: keep-alive\r\n\r\n"),
219     };
220     StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
221                                    data_writes2, arraysize(data_writes2));
222     mock_socket_factory_.AddSocketDataProvider(&data2);
223
224     // Expect that we get "content" and not "Bypass message", and that there's
225     // a "not-proxy" "Server:" header in the final response.
226     ExecuteRequestExpectingContentAndHeader("GET", "content",
227                                             "server", "not-proxy");
228
229     // We should also observe the bad proxy in the retry list.
230     TestBadProxies(1u, bad_proxy, "");
231   }
232
233   // Simulates a request through a proxy which returns a bypass, under a
234   // configuration where there is no valid bypass. |proxy_count| proxies
235   // are expected to be configured.
236   // Checks that the expected requests were issued, the bypass message was the
237   // final received content,  and all proxies were marked as bad.
238   void TestProxyFallbackFail(unsigned int proxy_count,
239                              const std::string& bad_proxy,
240                              const std::string& bad_proxy2) {
241     MockRead data_reads[] = {
242       MockRead("HTTP/1.1 200 OK\r\n"
243                "Chrome-Proxy: bypass=0\r\n\r\n"),
244       MockRead("Bypass message"),
245       MockRead(SYNCHRONOUS, OK),
246     };
247     MockWrite data_writes[] = {
248       MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
249                 "Host: www.google.com\r\n"
250                 "Proxy-Connection: keep-alive\r\n\r\n"),
251     };
252     StaticSocketDataProvider data1(data_reads, arraysize(data_reads),
253                                    data_writes, arraysize(data_writes));
254     StaticSocketDataProvider data2(data_reads, arraysize(data_reads),
255                                    data_writes, arraysize(data_writes));
256
257     mock_socket_factory_.AddSocketDataProvider(&data1);
258     if (proxy_count > 1)
259       mock_socket_factory_.AddSocketDataProvider(&data2);
260
261     // Expect that we get "Bypass message", and not "content"..
262     ExecuteRequestExpectingContentAndHeader("GET", "Bypass message", "", "");
263
264     // We should also observe the bad proxy or proxies in the retry list.
265     TestBadProxies(proxy_count, bad_proxy, bad_proxy2);
266   }
267
268   MockClientSocketFactory mock_socket_factory_;
269   MockHostResolver host_resolver_;
270   scoped_ptr<CertVerifier> cert_verifier_;
271   scoped_ptr<TransportSecurityState> transport_security_state_;
272   scoped_ptr<ProxyService> proxy_service_;
273   const scoped_refptr<SSLConfigService> ssl_config_service_;
274   scoped_refptr<HttpNetworkSession> network_session_;
275   scoped_ptr<HttpNetworkLayer> factory_;
276   HttpServerPropertiesImpl http_server_properties_;
277 };
278
279 TEST_F(HttpNetworkLayerTest, CreateAndDestroy) {
280   scoped_ptr<HttpTransaction> trans;
281   int rv = factory_->CreateTransaction(DEFAULT_PRIORITY, &trans);
282   EXPECT_EQ(OK, rv);
283   EXPECT_TRUE(trans.get() != NULL);
284 }
285
286 TEST_F(HttpNetworkLayerTest, Suspend) {
287   scoped_ptr<HttpTransaction> trans;
288   int rv = factory_->CreateTransaction(DEFAULT_PRIORITY, &trans);
289   EXPECT_EQ(OK, rv);
290
291   trans.reset();
292
293   factory_->OnSuspend();
294
295   rv = factory_->CreateTransaction(DEFAULT_PRIORITY, &trans);
296   EXPECT_EQ(ERR_NETWORK_IO_SUSPENDED, rv);
297
298   ASSERT_TRUE(trans == NULL);
299
300   factory_->OnResume();
301
302   rv = factory_->CreateTransaction(DEFAULT_PRIORITY, &trans);
303   EXPECT_EQ(OK, rv);
304 }
305
306 TEST_F(HttpNetworkLayerTest, GET) {
307   MockRead data_reads[] = {
308     MockRead("HTTP/1.0 200 OK\r\n\r\n"),
309     MockRead("hello world"),
310     MockRead(SYNCHRONOUS, OK),
311   };
312   MockWrite data_writes[] = {
313     MockWrite("GET / HTTP/1.1\r\n"
314               "Host: www.google.com\r\n"
315               "Connection: keep-alive\r\n"
316               "User-Agent: Foo/1.0\r\n\r\n"),
317   };
318   StaticSocketDataProvider data(data_reads, arraysize(data_reads),
319                                 data_writes, arraysize(data_writes));
320   mock_socket_factory_.AddSocketDataProvider(&data);
321
322   TestCompletionCallback callback;
323
324   HttpRequestInfo request_info;
325   request_info.url = GURL("http://www.google.com/");
326   request_info.method = "GET";
327   request_info.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
328                                        "Foo/1.0");
329   request_info.load_flags = LOAD_NORMAL;
330
331   scoped_ptr<HttpTransaction> trans;
332   int rv = factory_->CreateTransaction(DEFAULT_PRIORITY, &trans);
333   EXPECT_EQ(OK, rv);
334
335   rv = trans->Start(&request_info, callback.callback(), BoundNetLog());
336   rv = callback.GetResult(rv);
337   ASSERT_EQ(OK, rv);
338
339   std::string contents;
340   rv = ReadTransaction(trans.get(), &contents);
341   EXPECT_EQ(OK, rv);
342   EXPECT_EQ("hello world", contents);
343 }
344
345 // Proxy bypass tests. These tests run through various server-induced
346 // proxy bypass scenarios using both PAC file and fixed proxy params.
347 // The test scenarios are:
348 //  - bypass with two proxies configured and the first but not the second
349 //    is bypassed.
350 //  - bypass with one proxy configured and an explicit fallback to direct
351 //    connections
352 //  - bypass with two proxies configured and both are bypassed
353 //  - bypass with one proxy configured which is bypassed with no defined
354 //    fallback
355
356 #if defined(SPDY_PROXY_AUTH_ORIGIN)
357 TEST_F(HttpNetworkLayerTest, ServerTwoProxyBypassPac) {
358   std::string bad_proxy = GetChromeProxy();
359   ConfigureTestDependencies(ProxyService::CreateFixedFromPacResult(
360       "PROXY " + bad_proxy + "; PROXY good:8080"));
361   TestProxyFallback(bad_proxy);
362 }
363
364 TEST_F(HttpNetworkLayerTest, ServerTwoProxyBypassFixed) {
365   std::string bad_proxy = GetChromeProxy();
366   ConfigureTestDependencies(
367       ProxyService::CreateFixed(bad_proxy +", good:8080"));
368   TestProxyFallback(bad_proxy);
369 }
370
371 TEST_F(HttpNetworkLayerTest, BypassAndRetryIdempotentMethods) {
372   std::string bad_proxy = GetChromeProxy();
373   const struct {
374     std::string method;
375     std::string content;
376     bool expected_to_retry;
377   } tests[] = {
378     {
379       "GET",
380       "content",
381       true,
382     },
383     {
384       "OPTIONS",
385       "content",
386       true,
387     },
388     {
389       "HEAD",
390       "",
391       true,
392     },
393     {
394       "PUT",
395       "",
396       true,
397     },
398     {
399       "DELETE",
400       "content",
401       true,
402     },
403     {
404       "TRACE",
405       "content",
406       true,
407     },
408     {
409       "POST",
410       "Bypass message",
411       false,
412     },
413   };
414
415   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
416     ConfigureTestDependencies(
417         ProxyService::CreateFixed(bad_proxy +", good:8080"));
418     MockRead data_reads[] = {
419       MockRead("HTTP/1.1 200 OK\r\n"
420                "Chrome-Proxy: bypass=0\r\n\r\n"),
421       MockRead("Bypass message"),
422       MockRead(SYNCHRONOUS, OK),
423     };
424     TestProxyFallbackByMethodWithMockReads(bad_proxy, "", data_reads,
425                                            arraysize(data_reads),
426                                            tests[i].method,
427                                            tests[i].content,
428                                            tests[i].expected_to_retry, 1u);
429   }
430 }
431
432 TEST_F(HttpNetworkLayerTest, ServerOneProxyWithDirectBypassPac) {
433   std::string bad_proxy = GetChromeProxy();
434   ConfigureTestDependencies(ProxyService::CreateFixedFromPacResult(
435       "PROXY " + bad_proxy + "; DIRECT"));
436   TestProxyFallbackToDirect(bad_proxy);
437 }
438
439 TEST_F(HttpNetworkLayerTest, ServerOneProxyWithDirectBypassFixed) {
440   std::string bad_proxy = GetChromeProxy();
441   ConfigureTestDependencies(
442       ProxyService::CreateFixed(bad_proxy + ", direct://"));
443   TestProxyFallbackToDirect(bad_proxy);
444 }
445
446 #if defined(DATA_REDUCTION_FALLBACK_HOST)
447 TEST_F(HttpNetworkLayerTest, ServerTwoProxyDoubleBypassPac) {
448   std::string bad_proxy = GetChromeProxy();
449   std::string bad_proxy2 =
450       HostPortPair::FromURL(GURL(DATA_REDUCTION_FALLBACK_HOST)).ToString();
451   ConfigureTestDependencies(ProxyService::CreateFixedFromPacResult(
452       "PROXY " + bad_proxy + "; PROXY " + bad_proxy2));
453   TestProxyFallbackFail(2u, bad_proxy, bad_proxy2);
454 }
455
456 TEST_F(HttpNetworkLayerTest, ServerTwoProxyDoubleBypassFixed) {
457   std::string bad_proxy = GetChromeProxy();
458   std::string bad_proxy2 =
459       HostPortPair::FromURL(GURL(DATA_REDUCTION_FALLBACK_HOST)).ToString();
460   ConfigureTestDependencies(ProxyService::CreateFixed(
461     bad_proxy + ", " + bad_proxy2));
462   TestProxyFallbackFail(2u, bad_proxy, bad_proxy2);
463 }
464 #endif
465
466 TEST_F(HttpNetworkLayerTest, ServerOneProxyNoDirectBypassPac) {
467   std::string bad_proxy = GetChromeProxy();
468   ConfigureTestDependencies(ProxyService::CreateFixedFromPacResult(
469       "PROXY " + bad_proxy));
470   TestProxyFallbackFail(1u, bad_proxy, "");
471 }
472
473 TEST_F(HttpNetworkLayerTest, ServerOneProxyNoDirectBypassFixed) {
474   std::string bad_proxy = GetChromeProxy();
475   ConfigureTestDependencies(ProxyService::CreateFixed(bad_proxy));
476   TestProxyFallbackFail(1u, bad_proxy, "");
477 }
478
479 TEST_F(HttpNetworkLayerTest, ServerFallbackOn5xxError) {
480   // Verify that "500 Internal Server Error", "502 Bad Gateway", and
481   // "503 Service Unavailable" via the data reduction proxy induce proxy
482   // fallback to a second proxy, if configured.
483
484   // To configure this test, we need to wire up a custom proxy service to use
485   // a pair of proxies. We'll induce fallback via the first and return
486   // the expected data via the second.
487   std::string data_reduction_proxy(
488       HostPortPair::FromURL(GURL(SPDY_PROXY_AUTH_ORIGIN)).ToString());
489   std::string pac_string = base::StringPrintf(
490       "PROXY %s; PROXY good:8080", data_reduction_proxy.data());
491
492   std::string headers[] = {
493     "HTTP/1.1 500 Internal Server Error\r\n\r\n",
494     "HTTP/1.1 502 Bad Gateway\r\n\r\n",
495     "HTTP/1.1 503 Service Unavailable\r\n\r\n"
496   };
497
498   for (size_t i = 0; i < arraysize(headers); ++i) {
499     ConfigureTestDependencies(
500         ProxyService::CreateFixedFromPacResult(pac_string));
501
502     MockRead data_reads[] = {
503       MockRead(headers[i].c_str()),
504       MockRead("Bypass message"),
505       MockRead(SYNCHRONOUS, OK),
506     };
507
508     MockWrite data_writes[] = {
509       MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
510                 "Host: www.google.com\r\n"
511                 "Proxy-Connection: keep-alive\r\n\r\n"),
512     };
513
514     StaticSocketDataProvider data1(data_reads, arraysize(data_reads),
515                                    data_writes, arraysize(data_writes));
516     mock_socket_factory_.AddSocketDataProvider(&data1);
517
518     // Second data provider returns the expected content.
519     MockRead data_reads2[] = {
520       MockRead("HTTP/1.0 200 OK\r\n"
521                "Server: not-proxy\r\n\r\n"),
522       MockRead("content"),
523       MockRead(SYNCHRONOUS, OK),
524     };
525     MockWrite data_writes2[] = {
526       MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
527                 "Host: www.google.com\r\n"
528                 "Proxy-Connection: keep-alive\r\n\r\n"),
529     };
530
531     StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
532                                    data_writes2, arraysize(data_writes2));
533     mock_socket_factory_.AddSocketDataProvider(&data2);
534
535     TestCompletionCallback callback;
536
537     HttpRequestInfo request_info;
538     request_info.url = GURL("http://www.google.com/");
539     request_info.method = "GET";
540     request_info.load_flags = LOAD_NORMAL;
541
542     scoped_ptr<HttpTransaction> trans;
543     int rv = factory_->CreateTransaction(DEFAULT_PRIORITY, &trans);
544     EXPECT_EQ(OK, rv);
545
546     rv = trans->Start(&request_info, callback.callback(), BoundNetLog());
547     if (rv == ERR_IO_PENDING)
548       rv = callback.WaitForResult();
549     ASSERT_EQ(OK, rv);
550
551     std::string contents;
552     rv = ReadTransaction(trans.get(), &contents);
553     EXPECT_EQ(OK, rv);
554
555     // We should obtain content from the second socket provider write
556     // corresponding to the fallback proxy.
557     EXPECT_EQ("content", contents);
558     // We also have a server header here that isn't set by the proxy.
559     EXPECT_TRUE(trans->GetResponseInfo()->headers->HasHeaderValue(
560         "server", "not-proxy"));
561     // We should also observe the data reduction proxy in the retry list.
562     ASSERT_EQ(1u, proxy_service_->proxy_retry_info().size());
563     EXPECT_EQ(data_reduction_proxy,
564               (*proxy_service_->proxy_retry_info().begin()).first);
565   }
566 }
567 #endif  // defined(SPDY_PROXY_AUTH_ORIGIN)
568
569 TEST_F(HttpNetworkLayerTest, ProxyBypassIgnoredOnDirectConnectionPac) {
570   // Verify that a Chrome-Proxy header is ignored when returned from a directly
571   // connected origin server.
572   ConfigureTestDependencies(ProxyService::CreateFixedFromPacResult("DIRECT"));
573
574   MockRead data_reads[] = {
575     MockRead("HTTP/1.1 200 OK\r\n"
576              "Chrome-Proxy: bypass=0\r\n\r\n"),
577     MockRead("Bypass message"),
578     MockRead(SYNCHRONOUS, OK),
579   };
580   MockWrite data_writes[] = {
581     MockWrite("GET / HTTP/1.1\r\n"
582               "Host: www.google.com\r\n"
583               "Connection: keep-alive\r\n\r\n"),
584   };
585   StaticSocketDataProvider data1(data_reads, arraysize(data_reads),
586                                  data_writes, arraysize(data_writes));
587   mock_socket_factory_.AddSocketDataProvider(&data1);
588   TestCompletionCallback callback;
589
590   HttpRequestInfo request_info;
591   request_info.url = GURL("http://www.google.com/");
592   request_info.method = "GET";
593   request_info.load_flags = LOAD_NORMAL;
594
595   scoped_ptr<HttpTransaction> trans;
596   int rv = factory_->CreateTransaction(DEFAULT_PRIORITY, &trans);
597   EXPECT_EQ(OK, rv);
598
599   rv = trans->Start(&request_info, callback.callback(), BoundNetLog());
600   if (rv == ERR_IO_PENDING)
601     rv = callback.WaitForResult();
602   ASSERT_EQ(OK, rv);
603
604   // We should have read the original page data.
605   std::string contents;
606   rv = ReadTransaction(trans.get(), &contents);
607   EXPECT_EQ(OK, rv);
608   EXPECT_EQ("Bypass message", contents);
609
610   // We should have no entries in our bad proxy list.
611   ASSERT_EQ(0u, proxy_service_->proxy_retry_info().size());
612 }
613
614 #if defined(SPDY_PROXY_AUTH_ORIGIN)
615 TEST_F(HttpNetworkLayerTest, ServerFallbackWithProxyTimedBypass) {
616   // Verify that a Chrome-Proxy: bypass=<seconds> header induces proxy
617   // fallback to a second proxy, if configured.
618   std::string bad_proxy = GetChromeProxy();
619   ConfigureTestDependencies(ProxyService::CreateFixedFromPacResult(
620       "PROXY " + bad_proxy + "; PROXY good:8080"));
621
622   MockRead data_reads[] = {
623     MockRead("HTTP/1.1 200 OK\r\n"
624              "Connection: keep-alive\r\n"
625              "Chrome-Proxy: bypass=86400\r\n"
626              "Via: 1.1 Chrome-Compression-Proxy\r\n\r\n"),
627     MockRead("Bypass message"),
628     MockRead(SYNCHRONOUS, OK),
629   };
630
631   TestProxyFallbackWithMockReads(bad_proxy, "", data_reads,
632                                  arraysize(data_reads), 1u);
633   EXPECT_EQ(base::TimeDelta::FromSeconds(86400),
634             (*proxy_service_->proxy_retry_info().begin()).second.current_delay);
635 }
636
637 TEST_F(HttpNetworkLayerTest, ServerFallbackWithWrongViaHeader) {
638   // Verify that a Via header that lacks the Chrome-Proxy induces proxy fallback
639   // to a second proxy, if configured.
640   std::string chrome_proxy = GetChromeProxy();
641   ConfigureTestDependencies(ProxyService::CreateFixedFromPacResult(
642       "PROXY " + chrome_proxy + "; PROXY good:8080"));
643
644   MockRead data_reads[] = {
645     MockRead("HTTP/1.1 200 OK\r\n"
646              "Connection: keep-alive\r\n"
647              "Via: 1.0 some-other-proxy\r\n\r\n"),
648     MockRead("Bypass message"),
649     MockRead(SYNCHRONOUS, OK),
650   };
651
652   TestProxyFallbackWithMockReads(chrome_proxy, std::string(), data_reads,
653                                  arraysize(data_reads), 1u);
654 }
655
656 TEST_F(HttpNetworkLayerTest, ServerFallbackWithNoViaHeader) {
657   // Verify that the lack of a Via header induces proxy fallback to a second
658   // proxy, if configured.
659   std::string chrome_proxy = GetChromeProxy();
660   ConfigureTestDependencies(ProxyService::CreateFixedFromPacResult(
661       "PROXY " + chrome_proxy + "; PROXY good:8080"));
662
663   MockRead data_reads[] = {
664     MockRead("HTTP/1.1 200 OK\r\n"
665              "Connection: keep-alive\r\n\r\n"),
666     MockRead("Bypass message"),
667     MockRead(SYNCHRONOUS, OK),
668   };
669
670   TestProxyFallbackWithMockReads(chrome_proxy, std::string(), data_reads,
671                                  arraysize(data_reads), 1u);
672 }
673
674 TEST_F(HttpNetworkLayerTest, NoServerFallbackWith304Response) {
675   // Verify that Chrome will not be induced to bypass the Chrome proxy when
676   // the Chrome Proxy via header is absent on a 304.
677   std::string chrome_proxy = GetChromeProxy();
678   ConfigureTestDependencies(ProxyService::CreateFixedFromPacResult(
679       "PROXY " + chrome_proxy + "; PROXY good:8080"));
680
681   MockRead data_reads[] = {
682     MockRead("HTTP/1.1 304 Not Modified\r\n"
683              "Connection: keep-alive\r\n\r\n"),
684     MockRead(SYNCHRONOUS, OK),
685   };
686
687   TestProxyFallbackByMethodWithMockReads(chrome_proxy, std::string(),
688                                          data_reads, arraysize(data_reads),
689                                          "GET", std::string(), false, 0);
690 }
691
692 TEST_F(HttpNetworkLayerTest, NoServerFallbackWithChainedViaHeader) {
693   // Verify that Chrome will not be induced to bypass the Chrome proxy when
694   // the Chrome Proxy via header is present, even if that header is chained.
695   std::string chrome_proxy = GetChromeProxy();
696   ConfigureTestDependencies(ProxyService::CreateFixedFromPacResult(
697       "PROXY " + chrome_proxy + "; PROXY good:8080"));
698
699   MockRead data_reads[] = {
700     MockRead("HTTP/1.1 200 OK\r\n"
701              "Connection: keep-alive\r\n"
702              "Via: 1.1 Chrome-Compression-Proxy, 1.0 some-other-proxy\r\n\r\n"),
703     MockRead("Bypass message"),
704     MockRead(SYNCHRONOUS, OK),
705   };
706
707   TestProxyFallbackByMethodWithMockReads(chrome_proxy, std::string(),
708                                          data_reads, arraysize(data_reads),
709                                          "GET", "Bypass message", false, 0);
710 }
711
712 TEST_F(HttpNetworkLayerTest, NoServerFallbackWithDeprecatedViaHeader) {
713   // Verify that Chrome will not be induced to bypass the Chrome proxy when
714   // the deprecated Chrome Proxy via header is present, even if that header is
715   // chained.
716   std::string chrome_proxy = GetChromeProxy();
717   ConfigureTestDependencies(ProxyService::CreateFixedFromPacResult(
718       "PROXY " + chrome_proxy + "; PROXY good:8080"));
719
720   MockRead data_reads[] = {
721     MockRead("HTTP/1.1 200 OK\r\n"
722              "Connection: keep-alive\r\n"
723              "Via: 1.1 Chrome Compression Proxy\r\n\r\n"),
724     MockRead("Bypass message"),
725     MockRead(SYNCHRONOUS, OK),
726   };
727
728   TestProxyFallbackByMethodWithMockReads(chrome_proxy, std::string(),
729                                          data_reads, arraysize(data_reads),
730                                          "GET", "Bypass message", false, 0);
731 }
732
733 #if defined(DATA_REDUCTION_FALLBACK_HOST)
734 TEST_F(HttpNetworkLayerTest, ServerFallbackWithProxyTimedBypassAll) {
735   // Verify that a Chrome-Proxy: block=<seconds> header bypasses a
736   // a configured Chrome-Proxy and fallback and induces proxy fallback to a
737   // third proxy, if configured.
738   std::string bad_proxy = GetChromeProxy();
739   std::string fallback_proxy = GetChromeFallbackProxy();
740   ConfigureTestDependencies(ProxyService::CreateFixedFromPacResult(
741       "PROXY " + bad_proxy + "; PROXY " + fallback_proxy +
742       "; PROXY good:8080"));
743
744   MockRead data_reads[] = {
745     MockRead("HTTP/1.1 200 OK\r\n"
746              "Connection: keep-alive\r\n"
747              "Chrome-Proxy: block=86400\r\n"
748              "Via: 1.1 Chrome-Compression-Proxy\r\n\r\n"),
749     MockRead("Bypass message"),
750     MockRead(SYNCHRONOUS, OK),
751   };
752
753   TestProxyFallbackWithMockReads(bad_proxy, fallback_proxy, data_reads,
754                                  arraysize(data_reads), 2u);
755   EXPECT_EQ(base::TimeDelta::FromSeconds(86400),
756             (*proxy_service_->proxy_retry_info().begin()).second.current_delay);
757 }
758 #endif  // defined(DATA_REDUCTION_FALLBACK_HOST)
759 #endif  // defined(SPDY_PROXY_AUTH_ORIGIN)
760
761 TEST_F(HttpNetworkLayerTest, NetworkVerified) {
762   MockRead data_reads[] = {
763     MockRead("HTTP/1.0 200 OK\r\n\r\n"),
764     MockRead("hello world"),
765     MockRead(SYNCHRONOUS, OK),
766   };
767   MockWrite data_writes[] = {
768     MockWrite("GET / HTTP/1.1\r\n"
769               "Host: www.google.com\r\n"
770               "Connection: keep-alive\r\n"
771               "User-Agent: Foo/1.0\r\n\r\n"),
772   };
773   StaticSocketDataProvider data(data_reads, arraysize(data_reads),
774                                 data_writes, arraysize(data_writes));
775   mock_socket_factory_.AddSocketDataProvider(&data);
776
777   TestCompletionCallback callback;
778
779   HttpRequestInfo request_info;
780   request_info.url = GURL("http://www.google.com/");
781   request_info.method = "GET";
782   request_info.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
783                                        "Foo/1.0");
784   request_info.load_flags = LOAD_NORMAL;
785
786   scoped_ptr<HttpTransaction> trans;
787   int rv = factory_->CreateTransaction(DEFAULT_PRIORITY, &trans);
788   EXPECT_EQ(OK, rv);
789
790   rv = trans->Start(&request_info, callback.callback(), BoundNetLog());
791   ASSERT_EQ(OK, callback.GetResult(rv));
792
793   EXPECT_TRUE(trans->GetResponseInfo()->network_accessed);
794 }
795
796 TEST_F(HttpNetworkLayerTest, NetworkUnVerified) {
797   MockRead data_reads[] = {
798     MockRead(ASYNC, ERR_CONNECTION_RESET),
799   };
800   MockWrite data_writes[] = {
801     MockWrite("GET / HTTP/1.1\r\n"
802               "Host: www.google.com\r\n"
803               "Connection: keep-alive\r\n"
804               "User-Agent: Foo/1.0\r\n\r\n"),
805   };
806   StaticSocketDataProvider data(data_reads, arraysize(data_reads),
807                                 data_writes, arraysize(data_writes));
808   mock_socket_factory_.AddSocketDataProvider(&data);
809
810   TestCompletionCallback callback;
811
812   HttpRequestInfo request_info;
813   request_info.url = GURL("http://www.google.com/");
814   request_info.method = "GET";
815   request_info.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
816                                        "Foo/1.0");
817   request_info.load_flags = LOAD_NORMAL;
818
819   scoped_ptr<HttpTransaction> trans;
820   int rv = factory_->CreateTransaction(DEFAULT_PRIORITY, &trans);
821   EXPECT_EQ(OK, rv);
822
823   rv = trans->Start(&request_info, callback.callback(), BoundNetLog());
824   ASSERT_EQ(ERR_CONNECTION_RESET, callback.GetResult(rv));
825
826   // If the response info is null, that means that any consumer won't
827   // see the network accessed bit set.
828   EXPECT_EQ(NULL, trans->GetResponseInfo());
829 }
830
831 }  // namespace
832
833 }  // namespace net