Home | History | Annotate | Download | only in http
      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, NULL);
     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, NULL);
    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, NULL);
    289   EXPECT_EQ(OK, rv);
    290 
    291   trans.reset();
    292 
    293   factory_->OnSuspend();
    294 
    295   rv = factory_->CreateTransaction(DEFAULT_PRIORITY, &trans, NULL);
    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, NULL);
    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, NULL);
    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, NULL);
    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, NULL);
    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 #if defined(DATA_REDUCTION_FALLBACK_HOST)
    713 TEST_F(HttpNetworkLayerTest, ServerFallbackWithProxyTimedBypassAll) {
    714   // Verify that a Chrome-Proxy: block=<seconds> header bypasses a
    715   // a configured Chrome-Proxy and fallback and induces proxy fallback to a
    716   // third proxy, if configured.
    717   std::string bad_proxy = GetChromeProxy();
    718   std::string fallback_proxy = GetChromeFallbackProxy();
    719   ConfigureTestDependencies(ProxyService::CreateFixedFromPacResult(
    720       "PROXY " + bad_proxy + "; PROXY " + fallback_proxy +
    721       "; PROXY good:8080"));
    722 
    723   MockRead data_reads[] = {
    724     MockRead("HTTP/1.1 200 OK\r\n"
    725              "Connection: keep-alive\r\n"
    726              "Chrome-Proxy: block=86400\r\n"
    727              "Via: 1.1 Chrome Compression Proxy\r\n\r\n"),
    728     MockRead("Bypass message"),
    729     MockRead(SYNCHRONOUS, OK),
    730   };
    731 
    732   TestProxyFallbackWithMockReads(bad_proxy, fallback_proxy, data_reads,
    733                                  arraysize(data_reads), 2u);
    734   EXPECT_EQ(base::TimeDelta::FromSeconds(86400),
    735             (*proxy_service_->proxy_retry_info().begin()).second.current_delay);
    736 }
    737 #endif  // defined(DATA_REDUCTION_FALLBACK_HOST)
    738 #endif  // defined(SPDY_PROXY_AUTH_ORIGIN)
    739 
    740 TEST_F(HttpNetworkLayerTest, NetworkVerified) {
    741   MockRead data_reads[] = {
    742     MockRead("HTTP/1.0 200 OK\r\n\r\n"),
    743     MockRead("hello world"),
    744     MockRead(SYNCHRONOUS, OK),
    745   };
    746   MockWrite data_writes[] = {
    747     MockWrite("GET / HTTP/1.1\r\n"
    748               "Host: www.google.com\r\n"
    749               "Connection: keep-alive\r\n"
    750               "User-Agent: Foo/1.0\r\n\r\n"),
    751   };
    752   StaticSocketDataProvider data(data_reads, arraysize(data_reads),
    753                                 data_writes, arraysize(data_writes));
    754   mock_socket_factory_.AddSocketDataProvider(&data);
    755 
    756   TestCompletionCallback callback;
    757 
    758   HttpRequestInfo request_info;
    759   request_info.url = GURL("http://www.google.com/");
    760   request_info.method = "GET";
    761   request_info.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
    762                                        "Foo/1.0");
    763   request_info.load_flags = LOAD_NORMAL;
    764 
    765   scoped_ptr<HttpTransaction> trans;
    766   int rv = factory_->CreateTransaction(DEFAULT_PRIORITY, &trans, NULL);
    767   EXPECT_EQ(OK, rv);
    768 
    769   rv = trans->Start(&request_info, callback.callback(), BoundNetLog());
    770   ASSERT_EQ(OK, callback.GetResult(rv));
    771 
    772   EXPECT_TRUE(trans->GetResponseInfo()->network_accessed);
    773 }
    774 
    775 TEST_F(HttpNetworkLayerTest, NetworkUnVerified) {
    776   MockRead data_reads[] = {
    777     MockRead(ASYNC, ERR_CONNECTION_RESET),
    778   };
    779   MockWrite data_writes[] = {
    780     MockWrite("GET / HTTP/1.1\r\n"
    781               "Host: www.google.com\r\n"
    782               "Connection: keep-alive\r\n"
    783               "User-Agent: Foo/1.0\r\n\r\n"),
    784   };
    785   StaticSocketDataProvider data(data_reads, arraysize(data_reads),
    786                                 data_writes, arraysize(data_writes));
    787   mock_socket_factory_.AddSocketDataProvider(&data);
    788 
    789   TestCompletionCallback callback;
    790 
    791   HttpRequestInfo request_info;
    792   request_info.url = GURL("http://www.google.com/");
    793   request_info.method = "GET";
    794   request_info.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
    795                                        "Foo/1.0");
    796   request_info.load_flags = LOAD_NORMAL;
    797 
    798   scoped_ptr<HttpTransaction> trans;
    799   int rv = factory_->CreateTransaction(DEFAULT_PRIORITY, &trans, NULL);
    800   EXPECT_EQ(OK, rv);
    801 
    802   rv = trans->Start(&request_info, callback.callback(), BoundNetLog());
    803   ASSERT_EQ(ERR_CONNECTION_RESET, callback.GetResult(rv));
    804 
    805   // If the response info is null, that means that any consumer won't
    806   // see the network accessed bit set.
    807   EXPECT_EQ(NULL, trans->GetResponseInfo());
    808 }
    809 
    810 }  // namespace
    811 
    812 }  // namespace net
    813