| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/http/http_network_layer.h" | 5 #include "net/http/http_network_layer.h" |
| 6 | 6 |
| 7 #include "base/basictypes.h" |
| 7 #include "base/strings/stringprintf.h" | 8 #include "base/strings/stringprintf.h" |
| 8 #include "net/base/net_log.h" | 9 #include "net/base/net_log.h" |
| 9 #include "net/cert/mock_cert_verifier.h" | 10 #include "net/cert/mock_cert_verifier.h" |
| 10 #include "net/dns/mock_host_resolver.h" | 11 #include "net/dns/mock_host_resolver.h" |
| 11 #include "net/http/http_network_session.h" | 12 #include "net/http/http_network_session.h" |
| 12 #include "net/http/http_server_properties_impl.h" | 13 #include "net/http/http_server_properties_impl.h" |
| 13 #include "net/http/http_transaction_unittest.h" | 14 #include "net/http/http_transaction_unittest.h" |
| 14 #include "net/http/transport_security_state.h" | 15 #include "net/http/transport_security_state.h" |
| 15 #include "net/proxy/proxy_service.h" | 16 #include "net/proxy/proxy_service.h" |
| 16 #include "net/socket/socket_test_util.h" | 17 #include "net/socket/socket_test_util.h" |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 53 return HostPortPair::FromURL(GURL(SPDY_PROXY_AUTH_ORIGIN)).ToString(); | 54 return HostPortPair::FromURL(GURL(SPDY_PROXY_AUTH_ORIGIN)).ToString(); |
| 54 } | 55 } |
| 55 #endif | 56 #endif |
| 56 | 57 |
| 57 #if defined(SPDY_PROXY_AUTH_ORIGIN) && defined(DATA_REDUCTION_FALLBACK_HOST) | 58 #if defined(SPDY_PROXY_AUTH_ORIGIN) && defined(DATA_REDUCTION_FALLBACK_HOST) |
| 58 std::string GetChromeFallbackProxy() { | 59 std::string GetChromeFallbackProxy() { |
| 59 return HostPortPair::FromURL(GURL(DATA_REDUCTION_FALLBACK_HOST)).ToString(); | 60 return HostPortPair::FromURL(GURL(DATA_REDUCTION_FALLBACK_HOST)).ToString(); |
| 60 } | 61 } |
| 61 #endif | 62 #endif |
| 62 | 63 |
| 63 void ExecuteRequestExpectingContentAndHeader(const std::string& content, | 64 void ExecuteRequestExpectingContentAndHeader(const std::string& method, |
| 65 const std::string& content, |
| 64 const std::string& header, | 66 const std::string& header, |
| 65 const std::string& value) { | 67 const std::string& value) { |
| 66 TestCompletionCallback callback; | 68 TestCompletionCallback callback; |
| 67 | 69 |
| 68 HttpRequestInfo request_info; | 70 HttpRequestInfo request_info; |
| 69 request_info.url = GURL("http://www.google.com/"); | 71 request_info.url = GURL("http://www.google.com/"); |
| 70 request_info.method = "GET"; | 72 request_info.method = method; |
| 71 request_info.load_flags = LOAD_NORMAL; | 73 request_info.load_flags = LOAD_NORMAL; |
| 72 | 74 |
| 73 scoped_ptr<HttpTransaction> trans; | 75 scoped_ptr<HttpTransaction> trans; |
| 74 int rv = factory_->CreateTransaction(DEFAULT_PRIORITY, &trans, NULL); | 76 int rv = factory_->CreateTransaction(DEFAULT_PRIORITY, &trans, NULL); |
| 75 EXPECT_EQ(OK, rv); | 77 EXPECT_EQ(OK, rv); |
| 76 | 78 |
| 77 rv = trans->Start(&request_info, callback.callback(), BoundNetLog()); | 79 rv = trans->Start(&request_info, callback.callback(), BoundNetLog()); |
| 78 if (rv == ERR_IO_PENDING) | 80 if (rv == ERR_IO_PENDING) |
| 79 rv = callback.WaitForResult(); | 81 rv = callback.WaitForResult(); |
| 80 ASSERT_EQ(OK, rv); | 82 ASSERT_EQ(OK, rv); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 115 }; | 117 }; |
| 116 TestProxyFallbackWithMockReads(bad_proxy, "", data_reads, | 118 TestProxyFallbackWithMockReads(bad_proxy, "", data_reads, |
| 117 arraysize(data_reads), 1u); | 119 arraysize(data_reads), 1u); |
| 118 } | 120 } |
| 119 | 121 |
| 120 void TestProxyFallbackWithMockReads(const std::string& bad_proxy, | 122 void TestProxyFallbackWithMockReads(const std::string& bad_proxy, |
| 121 const std::string& bad_proxy2, | 123 const std::string& bad_proxy2, |
| 122 MockRead data_reads[], | 124 MockRead data_reads[], |
| 123 int data_reads_size, | 125 int data_reads_size, |
| 124 unsigned int expected_retry_info_size) { | 126 unsigned int expected_retry_info_size) { |
| 127 TestProxyFallbackByMethodWithMockReads(bad_proxy, bad_proxy2, data_reads, |
| 128 data_reads_size, "GET", "content", |
| 129 true, expected_retry_info_size); |
| 130 } |
| 131 |
| 132 void TestProxyFallbackByMethodWithMockReads( |
| 133 const std::string& bad_proxy, |
| 134 const std::string& bad_proxy2, |
| 135 MockRead data_reads[], |
| 136 int data_reads_size, |
| 137 std::string method, |
| 138 std::string content, |
| 139 bool retry_expected, |
| 140 unsigned int expected_retry_info_size) { |
| 141 std::string trailer = |
| 142 (method == "HEAD" || method == "PUT" || method == "POST") ? |
| 143 "Content-Length: 0\r\n\r\n" : "\r\n"; |
| 144 std::string request = |
| 145 base::StringPrintf("%s http://www.google.com/ HTTP/1.1\r\n" |
| 146 "Host: www.google.com\r\n" |
| 147 "Proxy-Connection: keep-alive\r\n" |
| 148 "%s", method.c_str(), trailer.c_str()); |
| 149 |
| 125 MockWrite data_writes[] = { | 150 MockWrite data_writes[] = { |
| 126 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n" | 151 MockWrite(request.c_str()), |
| 127 "Host: www.google.com\r\n" | |
| 128 "Proxy-Connection: keep-alive\r\n\r\n"), | |
| 129 }; | 152 }; |
| 130 | 153 |
| 131 StaticSocketDataProvider data1(data_reads, data_reads_size, | 154 StaticSocketDataProvider data1(data_reads, data_reads_size, |
| 132 data_writes, arraysize(data_writes)); | 155 data_writes, arraysize(data_writes)); |
| 133 mock_socket_factory_.AddSocketDataProvider(&data1); | 156 mock_socket_factory_.AddSocketDataProvider(&data1); |
| 134 | 157 |
| 135 // Second data provider returns the expected content. | 158 // Second data provider returns the expected content. |
| 136 MockRead data_reads2[] = { | 159 MockRead data_reads2[3]; |
| 137 MockRead("HTTP/1.0 200 OK\r\n" | 160 size_t data_reads2_index = 0; |
| 138 "Server: not-proxy\r\n\r\n"), | 161 data_reads2[data_reads2_index++] = MockRead("HTTP/1.0 200 OK\r\n" |
| 139 MockRead("content"), | 162 "Server: not-proxy\r\n\r\n"); |
| 140 MockRead(SYNCHRONOUS, OK), | 163 if (!content.empty()) |
| 164 data_reads2[data_reads2_index++] = MockRead(content.c_str()); |
| 165 data_reads2[data_reads2_index++] = MockRead(SYNCHRONOUS, OK); |
| 166 |
| 167 MockWrite data_writes2[] = { |
| 168 MockWrite(request.c_str()), |
| 141 }; | 169 }; |
| 142 MockWrite data_writes2[] = { | 170 StaticSocketDataProvider data2(data_reads2, data_reads2_index, |
| 143 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n" | |
| 144 "Host: www.google.com\r\n" | |
| 145 "Proxy-Connection: keep-alive\r\n\r\n"), | |
| 146 }; | |
| 147 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), | |
| 148 data_writes2, arraysize(data_writes2)); | 171 data_writes2, arraysize(data_writes2)); |
| 149 mock_socket_factory_.AddSocketDataProvider(&data2); | 172 mock_socket_factory_.AddSocketDataProvider(&data2); |
| 150 | 173 |
| 151 // Expect that we get "content" and not "Bypass message", and that there's | 174 // Expect that we get "content" and not "Bypass message", and that there's |
| 152 // a "not-proxy" "Server:" header in the final response. | 175 // a "not-proxy" "Server:" header in the final response. |
| 153 ExecuteRequestExpectingContentAndHeader("content", "server", "not-proxy"); | 176 if (retry_expected) { |
| 177 ExecuteRequestExpectingContentAndHeader(method, content, |
| 178 "server", "not-proxy"); |
| 179 } else { |
| 180 ExecuteRequestExpectingContentAndHeader(method, "Bypass message", "", ""); |
| 181 } |
| 154 | 182 |
| 155 // We should also observe the bad proxy in the retry list. | 183 // We should also observe the bad proxy in the retry list. |
| 156 TestBadProxies(expected_retry_info_size, bad_proxy, bad_proxy2); | 184 TestBadProxies(expected_retry_info_size, bad_proxy, bad_proxy2); |
| 157 } | 185 } |
| 158 | 186 |
| 159 // Simulates a request through a proxy which returns a bypass, which is then | 187 // Simulates a request through a proxy which returns a bypass, which is then |
| 160 // retried through a direct connection to the origin site. | 188 // retried through a direct connection to the origin site. |
| 161 // Checks that the expected requests were issued, the expected content was | 189 // Checks that the expected requests were issued, the expected content was |
| 162 // received, and the proxy |bad_proxy| was marked as bad. | 190 // received, and the proxy |bad_proxy| was marked as bad. |
| 163 void TestProxyFallbackToDirect(const std::string& bad_proxy) { | 191 void TestProxyFallbackToDirect(const std::string& bad_proxy) { |
| (...skipping 23 matching lines...) Expand all Loading... |
| 187 MockWrite("GET / HTTP/1.1\r\n" | 215 MockWrite("GET / HTTP/1.1\r\n" |
| 188 "Host: www.google.com\r\n" | 216 "Host: www.google.com\r\n" |
| 189 "Connection: keep-alive\r\n\r\n"), | 217 "Connection: keep-alive\r\n\r\n"), |
| 190 }; | 218 }; |
| 191 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), | 219 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), |
| 192 data_writes2, arraysize(data_writes2)); | 220 data_writes2, arraysize(data_writes2)); |
| 193 mock_socket_factory_.AddSocketDataProvider(&data2); | 221 mock_socket_factory_.AddSocketDataProvider(&data2); |
| 194 | 222 |
| 195 // Expect that we get "content" and not "Bypass message", and that there's | 223 // Expect that we get "content" and not "Bypass message", and that there's |
| 196 // a "not-proxy" "Server:" header in the final response. | 224 // a "not-proxy" "Server:" header in the final response. |
| 197 ExecuteRequestExpectingContentAndHeader("content", "server", "not-proxy"); | 225 ExecuteRequestExpectingContentAndHeader("GET", "content", |
| 226 "server", "not-proxy"); |
| 198 | 227 |
| 199 // We should also observe the bad proxy in the retry list. | 228 // We should also observe the bad proxy in the retry list. |
| 200 TestBadProxies(1u, bad_proxy, ""); | 229 TestBadProxies(1u, bad_proxy, ""); |
| 201 } | 230 } |
| 202 | 231 |
| 203 // Simulates a request through a proxy which returns a bypass, under a | 232 // Simulates a request through a proxy which returns a bypass, under a |
| 204 // configuration where there is no valid bypass. |proxy_count| proxies | 233 // configuration where there is no valid bypass. |proxy_count| proxies |
| 205 // are expected to be configured. | 234 // are expected to be configured. |
| 206 // Checks that the expected requests were issued, the bypass message was the | 235 // Checks that the expected requests were issued, the bypass message was the |
| 207 // final received content, and all proxies were marked as bad. | 236 // final received content, and all proxies were marked as bad. |
| (...skipping 14 matching lines...) Expand all Loading... |
| 222 StaticSocketDataProvider data1(data_reads, arraysize(data_reads), | 251 StaticSocketDataProvider data1(data_reads, arraysize(data_reads), |
| 223 data_writes, arraysize(data_writes)); | 252 data_writes, arraysize(data_writes)); |
| 224 StaticSocketDataProvider data2(data_reads, arraysize(data_reads), | 253 StaticSocketDataProvider data2(data_reads, arraysize(data_reads), |
| 225 data_writes, arraysize(data_writes)); | 254 data_writes, arraysize(data_writes)); |
| 226 | 255 |
| 227 mock_socket_factory_.AddSocketDataProvider(&data1); | 256 mock_socket_factory_.AddSocketDataProvider(&data1); |
| 228 if (proxy_count > 1) | 257 if (proxy_count > 1) |
| 229 mock_socket_factory_.AddSocketDataProvider(&data2); | 258 mock_socket_factory_.AddSocketDataProvider(&data2); |
| 230 | 259 |
| 231 // Expect that we get "Bypass message", and not "content".. | 260 // Expect that we get "Bypass message", and not "content".. |
| 232 ExecuteRequestExpectingContentAndHeader("Bypass message", "", ""); | 261 ExecuteRequestExpectingContentAndHeader("GET", "Bypass message", "", ""); |
| 233 | 262 |
| 234 // We should also observe the bad proxy or proxies in the retry list. | 263 // We should also observe the bad proxy or proxies in the retry list. |
| 235 TestBadProxies(proxy_count, bad_proxy, bad_proxy2); | 264 TestBadProxies(proxy_count, bad_proxy, bad_proxy2); |
| 236 } | 265 } |
| 237 | 266 |
| 238 MockClientSocketFactory mock_socket_factory_; | 267 MockClientSocketFactory mock_socket_factory_; |
| 239 MockHostResolver host_resolver_; | 268 MockHostResolver host_resolver_; |
| 240 scoped_ptr<CertVerifier> cert_verifier_; | 269 scoped_ptr<CertVerifier> cert_verifier_; |
| 241 scoped_ptr<TransportSecurityState> transport_security_state_; | 270 scoped_ptr<TransportSecurityState> transport_security_state_; |
| 242 scoped_ptr<ProxyService> proxy_service_; | 271 scoped_ptr<ProxyService> proxy_service_; |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 331 TestProxyFallback(bad_proxy); | 360 TestProxyFallback(bad_proxy); |
| 332 } | 361 } |
| 333 | 362 |
| 334 TEST_F(HttpNetworkLayerTest, ServerTwoProxyBypassFixed) { | 363 TEST_F(HttpNetworkLayerTest, ServerTwoProxyBypassFixed) { |
| 335 std::string bad_proxy = GetChromeProxy(); | 364 std::string bad_proxy = GetChromeProxy(); |
| 336 ConfigureTestDependencies( | 365 ConfigureTestDependencies( |
| 337 ProxyService::CreateFixed(bad_proxy +", good:8080")); | 366 ProxyService::CreateFixed(bad_proxy +", good:8080")); |
| 338 TestProxyFallback(bad_proxy); | 367 TestProxyFallback(bad_proxy); |
| 339 } | 368 } |
| 340 | 369 |
| 370 TEST_F(HttpNetworkLayerTest, BypassAndRetryIdempotentMethods) { |
| 371 std::string bad_proxy = GetChromeProxy(); |
| 372 const struct { |
| 373 std::string method; |
| 374 std::string content; |
| 375 bool expected_to_retry; |
| 376 } tests[] = { |
| 377 { |
| 378 "GET", |
| 379 "content", |
| 380 true, |
| 381 }, |
| 382 { |
| 383 "OPTIONS", |
| 384 "content", |
| 385 true, |
| 386 }, |
| 387 { |
| 388 "HEAD", |
| 389 "", |
| 390 true, |
| 391 }, |
| 392 { |
| 393 "PUT", |
| 394 "", |
| 395 true, |
| 396 }, |
| 397 { |
| 398 "DELETE", |
| 399 "content", |
| 400 true, |
| 401 }, |
| 402 { |
| 403 "TRACE", |
| 404 "content", |
| 405 true, |
| 406 }, |
| 407 { |
| 408 "POST", |
| 409 "Bypass message", |
| 410 false, |
| 411 }, |
| 412 }; |
| 413 |
| 414 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { |
| 415 ConfigureTestDependencies( |
| 416 ProxyService::CreateFixed(bad_proxy +", good:8080")); |
| 417 MockRead data_reads[] = { |
| 418 MockRead("HTTP/1.1 200 OK\r\n" |
| 419 "Chrome-Proxy: bypass=0\r\n\r\n"), |
| 420 MockRead("Bypass message"), |
| 421 MockRead(SYNCHRONOUS, OK), |
| 422 }; |
| 423 TestProxyFallbackByMethodWithMockReads(bad_proxy, "", data_reads, |
| 424 arraysize(data_reads), |
| 425 tests[i].method, |
| 426 tests[i].content, |
| 427 tests[i].expected_to_retry, 1u); |
| 428 } |
| 429 } |
| 430 |
| 341 TEST_F(HttpNetworkLayerTest, ServerOneProxyWithDirectBypassPac) { | 431 TEST_F(HttpNetworkLayerTest, ServerOneProxyWithDirectBypassPac) { |
| 342 std::string bad_proxy = GetChromeProxy(); | 432 std::string bad_proxy = GetChromeProxy(); |
| 343 ConfigureTestDependencies(ProxyService::CreateFixedFromPacResult( | 433 ConfigureTestDependencies(ProxyService::CreateFixedFromPacResult( |
| 344 "PROXY " + bad_proxy + "; DIRECT")); | 434 "PROXY " + bad_proxy + "; DIRECT")); |
| 345 TestProxyFallbackToDirect(bad_proxy); | 435 TestProxyFallbackToDirect(bad_proxy); |
| 346 } | 436 } |
| 347 | 437 |
| 348 TEST_F(HttpNetworkLayerTest, ServerOneProxyWithDirectBypassFixed) { | 438 TEST_F(HttpNetworkLayerTest, ServerOneProxyWithDirectBypassFixed) { |
| 349 std::string bad_proxy = GetChromeProxy(); | 439 std::string bad_proxy = GetChromeProxy(); |
| 350 ConfigureTestDependencies( | 440 ConfigureTestDependencies( |
| (...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 635 ASSERT_EQ(ERR_CONNECTION_RESET, callback.GetResult(rv)); | 725 ASSERT_EQ(ERR_CONNECTION_RESET, callback.GetResult(rv)); |
| 636 | 726 |
| 637 // If the response info is null, that means that any consumer won't | 727 // If the response info is null, that means that any consumer won't |
| 638 // see the network accessed bit set. | 728 // see the network accessed bit set. |
| 639 EXPECT_EQ(NULL, trans->GetResponseInfo()); | 729 EXPECT_EQ(NULL, trans->GetResponseInfo()); |
| 640 } | 730 } |
| 641 | 731 |
| 642 } // namespace | 732 } // namespace |
| 643 | 733 |
| 644 } // namespace net | 734 } // namespace net |
| OLD | NEW |