| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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_stream_factory_impl.h" | 5 #include "net/http/http_stream_factory_impl.h" |
| 6 | 6 |
| 7 #include <string> | 7 #include <string> |
| 8 | 8 |
| 9 #include "base/basictypes.h" | 9 #include "base/basictypes.h" |
| 10 #include "net/base/capturing_net_log.h" | |
| 11 #include "net/base/cert_verifier.h" | 10 #include "net/base/cert_verifier.h" |
| 12 #include "net/base/mock_host_resolver.h" | 11 #include "net/base/mock_host_resolver.h" |
| 13 #include "net/base/net_log.h" | 12 #include "net/base/net_log.h" |
| 14 #include "net/base/ssl_config_service_defaults.h" | 13 #include "net/base/ssl_config_service_defaults.h" |
| 15 #include "net/base/test_completion_callback.h" | 14 #include "net/base/test_completion_callback.h" |
| 16 #include "net/http/http_auth_handler_factory.h" | 15 #include "net/http/http_auth_handler_factory.h" |
| 17 #include "net/http/http_network_session.h" | 16 #include "net/http/http_network_session.h" |
| 18 #include "net/http/http_network_session_peer.h" | 17 #include "net/http/http_network_session_peer.h" |
| 19 #include "net/http/http_request_info.h" | 18 #include "net/http/http_request_info.h" |
| 20 #include "net/http/http_server_properties_impl.h" | 19 #include "net/http/http_server_properties_impl.h" |
| (...skipping 21 matching lines...) Expand all Loading... |
| 42 void WaitForPreconnects() { | 41 void WaitForPreconnects() { |
| 43 while (!preconnect_done_) { | 42 while (!preconnect_done_) { |
| 44 waiting_for_preconnect_ = true; | 43 waiting_for_preconnect_ = true; |
| 45 MessageLoop::current()->Run(); | 44 MessageLoop::current()->Run(); |
| 46 waiting_for_preconnect_ = false; | 45 waiting_for_preconnect_ = false; |
| 47 } | 46 } |
| 48 } | 47 } |
| 49 | 48 |
| 50 private: | 49 private: |
| 51 // HttpStreamFactoryImpl methods. | 50 // HttpStreamFactoryImpl methods. |
| 52 virtual void OnPreconnectsCompleteInternal() { | 51 virtual void OnPreconnectsCompleteInternal() OVERRIDE { |
| 53 preconnect_done_ = true; | 52 preconnect_done_ = true; |
| 54 if (waiting_for_preconnect_) | 53 if (waiting_for_preconnect_) |
| 55 MessageLoop::current()->Quit(); | 54 MessageLoop::current()->Quit(); |
| 56 } | 55 } |
| 57 | 56 |
| 58 bool preconnect_done_; | 57 bool preconnect_done_; |
| 59 bool waiting_for_preconnect_; | 58 bool waiting_for_preconnect_; |
| 60 }; | 59 }; |
| 61 | 60 |
| 62 class StreamRequestWaiter : public HttpStreamRequest::Delegate { | 61 class StreamRequestWaiter : public HttpStreamRequest::Delegate { |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 155 bool ssl; | 154 bool ssl; |
| 156 }; | 155 }; |
| 157 | 156 |
| 158 TestCase kTests[] = { | 157 TestCase kTests[] = { |
| 159 { 1, false }, | 158 { 1, false }, |
| 160 { 2, false }, | 159 { 2, false }, |
| 161 { 1, true}, | 160 { 1, true}, |
| 162 { 2, true}, | 161 { 2, true}, |
| 163 }; | 162 }; |
| 164 | 163 |
| 165 void PreconnectHelper(const TestCase& test, | 164 void PreconnectHelperForURL(int num_streams, |
| 166 HttpNetworkSession* session) { | 165 const GURL& url, |
| 166 HttpNetworkSession* session) { |
| 167 HttpNetworkSessionPeer peer(session); | 167 HttpNetworkSessionPeer peer(session); |
| 168 MockHttpStreamFactoryImpl* mock_factory = | 168 MockHttpStreamFactoryImpl* mock_factory = |
| 169 new MockHttpStreamFactoryImpl(session); | 169 new MockHttpStreamFactoryImpl(session); |
| 170 peer.SetHttpStreamFactory(mock_factory); | 170 peer.SetHttpStreamFactory(mock_factory); |
| 171 SSLConfig ssl_config; | 171 SSLConfig ssl_config; |
| 172 session->ssl_config_service()->GetSSLConfig(&ssl_config); | 172 session->ssl_config_service()->GetSSLConfig(&ssl_config); |
| 173 | 173 |
| 174 HttpRequestInfo request; | 174 HttpRequestInfo request; |
| 175 request.method = "GET"; | 175 request.method = "GET"; |
| 176 request.url = test.ssl ? GURL("https://www.google.com") : | 176 request.url = url; |
| 177 GURL("http://www.google.com"); | |
| 178 request.load_flags = 0; | 177 request.load_flags = 0; |
| 179 | 178 |
| 180 ProxyInfo proxy_info; | 179 session->http_stream_factory()->PreconnectStreams( |
| 181 TestOldCompletionCallback callback; | 180 num_streams, request, ssl_config, ssl_config, BoundNetLog()); |
| 181 mock_factory->WaitForPreconnects(); |
| 182 }; |
| 182 | 183 |
| 183 session->http_stream_factory()->PreconnectStreams( | 184 void PreconnectHelper(const TestCase& test, |
| 184 test.num_streams, request, ssl_config, ssl_config, BoundNetLog()); | 185 HttpNetworkSession* session) { |
| 185 mock_factory->WaitForPreconnects(); | 186 GURL url = test.ssl ? GURL("https://www.google.com") : |
| 187 GURL("http://www.google.com"); |
| 188 PreconnectHelperForURL(test.num_streams, url, session); |
| 186 }; | 189 }; |
| 187 | 190 |
| 188 template<typename ParentPool> | 191 template<typename ParentPool> |
| 189 class CapturePreconnectsSocketPool : public ParentPool { | 192 class CapturePreconnectsSocketPool : public ParentPool { |
| 190 public: | 193 public: |
| 191 CapturePreconnectsSocketPool(HostResolver* host_resolver, | 194 CapturePreconnectsSocketPool(HostResolver* host_resolver, |
| 192 CertVerifier* cert_verifier); | 195 CertVerifier* cert_verifier); |
| 193 | 196 |
| 194 int last_num_streams() const { | 197 int last_num_streams() const { |
| 195 return last_num_streams_; | 198 return last_num_streams_; |
| 196 } | 199 } |
| 197 | 200 |
| 198 virtual int RequestSocket(const std::string& group_name, | 201 virtual int RequestSocket(const std::string& group_name, |
| 199 const void* socket_params, | 202 const void* socket_params, |
| 200 RequestPriority priority, | 203 RequestPriority priority, |
| 201 ClientSocketHandle* handle, | 204 ClientSocketHandle* handle, |
| 202 OldCompletionCallback* callback, | 205 OldCompletionCallback* callback, |
| 203 const BoundNetLog& net_log) { | 206 const BoundNetLog& net_log) OVERRIDE { |
| 204 ADD_FAILURE(); | 207 ADD_FAILURE(); |
| 205 return ERR_UNEXPECTED; | 208 return ERR_UNEXPECTED; |
| 206 } | 209 } |
| 207 | 210 |
| 208 virtual void RequestSockets(const std::string& group_name, | 211 virtual void RequestSockets(const std::string& group_name, |
| 209 const void* socket_params, | 212 const void* socket_params, |
| 210 int num_sockets, | 213 int num_sockets, |
| 211 const BoundNetLog& net_log) { | 214 const BoundNetLog& net_log) OVERRIDE { |
| 212 last_num_streams_ = num_sockets; | 215 last_num_streams_ = num_sockets; |
| 213 } | 216 } |
| 214 | 217 |
| 215 virtual void CancelRequest(const std::string& group_name, | 218 virtual void CancelRequest(const std::string& group_name, |
| 216 ClientSocketHandle* handle) { | 219 ClientSocketHandle* handle) OVERRIDE { |
| 217 ADD_FAILURE(); | 220 ADD_FAILURE(); |
| 218 } | 221 } |
| 219 virtual void ReleaseSocket(const std::string& group_name, | 222 virtual void ReleaseSocket(const std::string& group_name, |
| 220 StreamSocket* socket, | 223 StreamSocket* socket, |
| 221 int id) { | 224 int id) OVERRIDE { |
| 222 ADD_FAILURE(); | 225 ADD_FAILURE(); |
| 223 } | 226 } |
| 224 virtual void CloseIdleSockets() { | 227 virtual void CloseIdleSockets() OVERRIDE { |
| 225 ADD_FAILURE(); | 228 ADD_FAILURE(); |
| 226 } | 229 } |
| 227 virtual int IdleSocketCount() const { | 230 virtual int IdleSocketCount() const OVERRIDE { |
| 228 ADD_FAILURE(); | 231 ADD_FAILURE(); |
| 229 return 0; | 232 return 0; |
| 230 } | 233 } |
| 231 virtual int IdleSocketCountInGroup(const std::string& group_name) const { | 234 virtual int IdleSocketCountInGroup( |
| 235 const std::string& group_name) const OVERRIDE { |
| 232 ADD_FAILURE(); | 236 ADD_FAILURE(); |
| 233 return 0; | 237 return 0; |
| 234 } | 238 } |
| 235 virtual LoadState GetLoadState(const std::string& group_name, | 239 virtual LoadState GetLoadState( |
| 236 const ClientSocketHandle* handle) const { | 240 const std::string& group_name, |
| 241 const ClientSocketHandle* handle) const OVERRIDE { |
| 237 ADD_FAILURE(); | 242 ADD_FAILURE(); |
| 238 return LOAD_STATE_IDLE; | 243 return LOAD_STATE_IDLE; |
| 239 } | 244 } |
| 240 virtual base::TimeDelta ConnectionTimeout() const { | 245 virtual base::TimeDelta ConnectionTimeout() const OVERRIDE { |
| 241 return base::TimeDelta(); | 246 return base::TimeDelta(); |
| 242 } | 247 } |
| 243 | 248 |
| 244 private: | 249 private: |
| 245 int last_num_streams_; | 250 int last_num_streams_; |
| 246 }; | 251 }; |
| 247 | 252 |
| 248 typedef CapturePreconnectsSocketPool<TransportClientSocketPool> | 253 typedef CapturePreconnectsSocketPool<TransportClientSocketPool> |
| 249 CapturePreconnectsTransportSocketPool; | 254 CapturePreconnectsTransportSocketPool; |
| 250 typedef CapturePreconnectsSocketPool<HttpProxyClientSocketPool> | 255 typedef CapturePreconnectsSocketPool<HttpProxyClientSocketPool> |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 382 PreconnectHelper(kTests[i], session); | 387 PreconnectHelper(kTests[i], session); |
| 383 // We shouldn't be preconnecting if we have an existing session, which is | 388 // We shouldn't be preconnecting if we have an existing session, which is |
| 384 // the case for https://www.google.com. | 389 // the case for https://www.google.com. |
| 385 if (kTests[i].ssl) | 390 if (kTests[i].ssl) |
| 386 EXPECT_EQ(-1, ssl_conn_pool->last_num_streams()); | 391 EXPECT_EQ(-1, ssl_conn_pool->last_num_streams()); |
| 387 else | 392 else |
| 388 EXPECT_EQ(kTests[i].num_streams, transport_conn_pool->last_num_streams()); | 393 EXPECT_EQ(kTests[i].num_streams, transport_conn_pool->last_num_streams()); |
| 389 } | 394 } |
| 390 } | 395 } |
| 391 | 396 |
| 397 // Verify that preconnects to unsafe ports are cancelled before they reach |
| 398 // the SocketPool. |
| 399 TEST(HttpStreamFactoryTest, PreconnectUnsafePort) { |
| 400 ASSERT_FALSE(IsPortAllowedByDefault(7)); |
| 401 ASSERT_FALSE(IsPortAllowedByOverride(7)); |
| 402 |
| 403 SessionDependencies session_deps(ProxyService::CreateDirect()); |
| 404 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps)); |
| 405 HttpNetworkSessionPeer peer(session); |
| 406 CapturePreconnectsTransportSocketPool* transport_conn_pool = |
| 407 new CapturePreconnectsTransportSocketPool( |
| 408 session_deps.host_resolver.get(), |
| 409 session_deps.cert_verifier.get()); |
| 410 MockClientSocketPoolManager* mock_pool_manager = |
| 411 new MockClientSocketPoolManager; |
| 412 mock_pool_manager->SetTransportSocketPool(transport_conn_pool); |
| 413 peer.SetClientSocketPoolManager(mock_pool_manager); |
| 414 |
| 415 PreconnectHelperForURL(1, GURL("http://www.google.com:7"), session); |
| 416 |
| 417 EXPECT_EQ(-1, transport_conn_pool->last_num_streams()); |
| 418 } |
| 419 |
| 392 TEST(HttpStreamFactoryTest, JobNotifiesProxy) { | 420 TEST(HttpStreamFactoryTest, JobNotifiesProxy) { |
| 393 const char* kProxyString = "PROXY bad:99; PROXY maybe:80; DIRECT"; | 421 const char* kProxyString = "PROXY bad:99; PROXY maybe:80; DIRECT"; |
| 394 SessionDependencies session_deps( | 422 SessionDependencies session_deps( |
| 395 ProxyService::CreateFixedFromPacResult(kProxyString)); | 423 ProxyService::CreateFixedFromPacResult(kProxyString)); |
| 396 | 424 |
| 397 // First connection attempt fails | 425 // First connection attempt fails |
| 398 StaticSocketDataProvider socket_data1; | 426 StaticSocketDataProvider socket_data1; |
| 399 socket_data1.set_connect_data(MockConnect(true, ERR_ADDRESS_UNREACHABLE)); | 427 socket_data1.set_connect_data(MockConnect(true, ERR_ADDRESS_UNREACHABLE)); |
| 400 session_deps.socket_factory.AddSocketDataProvider(&socket_data1); | 428 session_deps.socket_factory.AddSocketDataProvider(&socket_data1); |
| 401 | 429 |
| 402 // Second connection attempt succeeds | 430 // Second connection attempt succeeds |
| 403 StaticSocketDataProvider socket_data2; | 431 StaticSocketDataProvider socket_data2; |
| 404 socket_data2.set_connect_data(MockConnect(true, OK)); | 432 socket_data2.set_connect_data(MockConnect(true, OK)); |
| 405 session_deps.socket_factory.AddSocketDataProvider(&socket_data2); | 433 session_deps.socket_factory.AddSocketDataProvider(&socket_data2); |
| 406 | 434 |
| 407 CapturingBoundNetLog log(CapturingNetLog::kUnbounded); | |
| 408 EXPECT_TRUE(log.bound().IsLoggingAllEvents()); | |
| 409 | |
| 410 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps)); | 435 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps)); |
| 411 | 436 |
| 412 // Now request a stream. It should succeed using the second proxy in the | 437 // Now request a stream. It should succeed using the second proxy in the |
| 413 // list. | 438 // list. |
| 414 HttpRequestInfo request_info; | 439 HttpRequestInfo request_info; |
| 415 request_info.method = "GET"; | 440 request_info.method = "GET"; |
| 416 request_info.url = GURL("http://www.google.com"); | 441 request_info.url = GURL("http://www.google.com"); |
| 417 request_info.load_flags = 0; | 442 request_info.load_flags = 0; |
| 418 | 443 |
| 419 SSLConfig ssl_config; | 444 SSLConfig ssl_config; |
| 420 StreamRequestWaiter waiter; | 445 StreamRequestWaiter waiter; |
| 421 scoped_ptr<HttpStreamRequest> request( | 446 scoped_ptr<HttpStreamRequest> request( |
| 422 session->http_stream_factory()->RequestStream(request_info, ssl_config, | 447 session->http_stream_factory()->RequestStream(request_info, ssl_config, |
| 423 ssl_config, &waiter, | 448 ssl_config, &waiter, |
| 424 log.bound())); | 449 BoundNetLog())); |
| 425 waiter.WaitForStream(); | 450 waiter.WaitForStream(); |
| 426 | 451 |
| 427 // The proxy that failed should now be known to the proxy_service as bad. | 452 // The proxy that failed should now be known to the proxy_service as bad. |
| 428 const ProxyRetryInfoMap& retry_info = | 453 const ProxyRetryInfoMap& retry_info = |
| 429 session->proxy_service()->proxy_retry_info(); | 454 session->proxy_service()->proxy_retry_info(); |
| 430 EXPECT_EQ(1u, retry_info.size()); | 455 EXPECT_EQ(1u, retry_info.size()); |
| 431 ProxyRetryInfoMap::const_iterator iter = retry_info.find("bad:99"); | 456 ProxyRetryInfoMap::const_iterator iter = retry_info.find("bad:99"); |
| 432 EXPECT_TRUE(iter != retry_info.end()); | 457 EXPECT_TRUE(iter != retry_info.end()); |
| 433 } | 458 } |
| 434 | 459 |
| 435 } // namespace | 460 } // namespace |
| 436 | 461 |
| 437 } // namespace net | 462 } // namespace net |
| OLD | NEW |