http_network_layer_unittest.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
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 23namespace net { 24 25namespace { 26 27class 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_of_retry, 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_of_retry.empty()) 165 data_reads2[data_reads2_index++] = MockRead(content_of_retry.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_of_retry, 179 "server", "not-proxy"); 180 } else { 181 ExecuteRequestExpectingContentAndHeader(method, "Bypass message", "", ""); 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 279TEST_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 286TEST_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 306TEST_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) 357TEST_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 364TEST_F(HttpNetworkLayerTest, ServerTwoProxyBypassFixed) { 365 std::string bad_proxy = GetChromeProxy(); 366 ConfigureTestDependencies( 367 ProxyService::CreateFixed(bad_proxy +", good:8080")); 368 TestProxyFallback(bad_proxy); 369} 370 371TEST_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 432TEST_F(HttpNetworkLayerTest, ServerOneProxyWithDirectBypassPac) { 433 std::string bad_proxy = GetChromeProxy(); 434 ConfigureTestDependencies(ProxyService::CreateFixedFromPacResult( 435 "PROXY " + bad_proxy + "; DIRECT")); 436 TestProxyFallbackToDirect(bad_proxy); 437} 438 439TEST_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) 447TEST_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 456TEST_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 466TEST_F(HttpNetworkLayerTest, ServerOneProxyNoDirectBypassPac) { 467 std::string bad_proxy = GetChromeProxy(); 468 ConfigureTestDependencies(ProxyService::CreateFixedFromPacResult( 469 "PROXY " + bad_proxy)); 470 TestProxyFallbackFail(1u, bad_proxy, ""); 471} 472 473TEST_F(HttpNetworkLayerTest, ServerOneProxyNoDirectBypassFixed) { 474 std::string bad_proxy = GetChromeProxy(); 475 ConfigureTestDependencies(ProxyService::CreateFixed(bad_proxy)); 476 TestProxyFallbackFail(1u, bad_proxy, ""); 477} 478 479TEST_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 569TEST_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) 615TEST_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 637TEST_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 656TEST_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 674TEST_F(HttpNetworkLayerTest, NoServerFallbackWithChainedViaHeader) { 675 // Verify that Chrome will not be induced to bypass the Chrome proxy when 676 // the Chrome Proxy via header is present, even if that header is chained. 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 200 OK\r\n" 683 "Connection: keep-alive\r\n" 684 "Via: 1.1 Chrome-Compression-Proxy, 1.0 some-other-proxy\r\n\r\n"), 685 MockRead("Bypass message"), 686 MockRead(SYNCHRONOUS, OK), 687 }; 688 689 TestProxyFallbackByMethodWithMockReads(chrome_proxy, std::string(), 690 data_reads, arraysize(data_reads), 691 "GET", std::string(), false, 0); 692} 693 694TEST_F(HttpNetworkLayerTest, NoServerFallbackWithDeprecatedViaHeader) { 695 // Verify that Chrome will not be induced to bypass the Chrome proxy when 696 // the Chrome Proxy via header is present, even if that header is chained. 697 std::string chrome_proxy = GetChromeProxy(); 698 ConfigureTestDependencies(ProxyService::CreateFixedFromPacResult( 699 "PROXY " + chrome_proxy + "; PROXY good:8080")); 700 701 MockRead data_reads[] = { 702 MockRead("HTTP/1.1 200 OK\r\n" 703 "Connection: keep-alive\r\n" 704 "Via: 1.1 Chrome Compression Proxy\r\n\r\n"), 705 MockRead("Bypass message"), 706 MockRead(SYNCHRONOUS, OK), 707 }; 708 709 TestProxyFallbackByMethodWithMockReads(chrome_proxy, std::string(), 710 data_reads, arraysize(data_reads), 711 "GET", std::string(), false, 0); 712} 713 714#if defined(DATA_REDUCTION_FALLBACK_HOST) 715TEST_F(HttpNetworkLayerTest, ServerFallbackWithProxyTimedBypassAll) { 716 // Verify that a Chrome-Proxy: block=<seconds> header bypasses a 717 // a configured Chrome-Proxy and fallback and induces proxy fallback to a 718 // third proxy, if configured. 719 std::string bad_proxy = GetChromeProxy(); 720 std::string fallback_proxy = GetChromeFallbackProxy(); 721 ConfigureTestDependencies(ProxyService::CreateFixedFromPacResult( 722 "PROXY " + bad_proxy + "; PROXY " + fallback_proxy + 723 "; PROXY good:8080")); 724 725 MockRead data_reads[] = { 726 MockRead("HTTP/1.1 200 OK\r\n" 727 "Connection: keep-alive\r\n" 728 "Chrome-Proxy: block=86400\r\n" 729 "Via: 1.1 Chrome-Compression-Proxy\r\n\r\n"), 730 MockRead("Bypass message"), 731 MockRead(SYNCHRONOUS, OK), 732 }; 733 734 TestProxyFallbackWithMockReads(bad_proxy, fallback_proxy, data_reads, 735 arraysize(data_reads), 2u); 736 EXPECT_EQ(base::TimeDelta::FromSeconds(86400), 737 (*proxy_service_->proxy_retry_info().begin()).second.current_delay); 738} 739#endif // defined(DATA_REDUCTION_FALLBACK_HOST) 740#endif // defined(SPDY_PROXY_AUTH_ORIGIN) 741 742TEST_F(HttpNetworkLayerTest, NetworkVerified) { 743 MockRead data_reads[] = { 744 MockRead("HTTP/1.0 200 OK\r\n\r\n"), 745 MockRead("hello world"), 746 MockRead(SYNCHRONOUS, OK), 747 }; 748 MockWrite data_writes[] = { 749 MockWrite("GET / HTTP/1.1\r\n" 750 "Host: www.google.com\r\n" 751 "Connection: keep-alive\r\n" 752 "User-Agent: Foo/1.0\r\n\r\n"), 753 }; 754 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 755 data_writes, arraysize(data_writes)); 756 mock_socket_factory_.AddSocketDataProvider(&data); 757 758 TestCompletionCallback callback; 759 760 HttpRequestInfo request_info; 761 request_info.url = GURL("http://www.google.com/"); 762 request_info.method = "GET"; 763 request_info.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent, 764 "Foo/1.0"); 765 request_info.load_flags = LOAD_NORMAL; 766 767 scoped_ptr<HttpTransaction> trans; 768 int rv = factory_->CreateTransaction(DEFAULT_PRIORITY, &trans); 769 EXPECT_EQ(OK, rv); 770 771 rv = trans->Start(&request_info, callback.callback(), BoundNetLog()); 772 ASSERT_EQ(OK, callback.GetResult(rv)); 773 774 EXPECT_TRUE(trans->GetResponseInfo()->network_accessed); 775} 776 777TEST_F(HttpNetworkLayerTest, NetworkUnVerified) { 778 MockRead data_reads[] = { 779 MockRead(ASYNC, ERR_CONNECTION_RESET), 780 }; 781 MockWrite data_writes[] = { 782 MockWrite("GET / HTTP/1.1\r\n" 783 "Host: www.google.com\r\n" 784 "Connection: keep-alive\r\n" 785 "User-Agent: Foo/1.0\r\n\r\n"), 786 }; 787 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 788 data_writes, arraysize(data_writes)); 789 mock_socket_factory_.AddSocketDataProvider(&data); 790 791 TestCompletionCallback callback; 792 793 HttpRequestInfo request_info; 794 request_info.url = GURL("http://www.google.com/"); 795 request_info.method = "GET"; 796 request_info.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent, 797 "Foo/1.0"); 798 request_info.load_flags = LOAD_NORMAL; 799 800 scoped_ptr<HttpTransaction> trans; 801 int rv = factory_->CreateTransaction(DEFAULT_PRIORITY, &trans); 802 EXPECT_EQ(OK, rv); 803 804 rv = trans->Start(&request_info, callback.callback(), BoundNetLog()); 805 ASSERT_EQ(ERR_CONNECTION_RESET, callback.GetResult(rv)); 806 807 // If the response info is null, that means that any consumer won't 808 // see the network accessed bit set. 809 EXPECT_EQ(NULL, trans->GetResponseInfo()); 810} 811 812} // namespace 813 814} // namespace net 815