diff options
Diffstat (limited to 'net')
32 files changed, 1046 insertions, 692 deletions
diff --git a/net/http/http_cache.cc b/net/http/http_cache.cc index 7c35f69..a821a30 100644 --- a/net/http/http_cache.cc +++ b/net/http/http_cache.cc @@ -451,15 +451,12 @@ void HttpCache::WriteMetadata(const GURL& url, writer->Write(url, expected_response_time, buf, buf_len); } -void HttpCache::CloseCurrentConnections() { +void HttpCache::CloseAllConnections() { net::HttpNetworkLayer* network = static_cast<net::HttpNetworkLayer*>(network_layer_.get()); HttpNetworkSession* session = network->GetSession(); - if (session) { - session->FlushSocketPools(); - if (session->spdy_session_pool()) - session->spdy_session_pool()->CloseCurrentSessions(); - } + if (session) + session->CloseAllConnections(); } int HttpCache::CreateTransaction(scoped_ptr<HttpTransaction>* trans) { diff --git a/net/http/http_cache.h b/net/http/http_cache.h index cdbddfe..ba7a18e 100644 --- a/net/http/http_cache.h +++ b/net/http/http_cache.h @@ -176,7 +176,7 @@ class HttpCache : public HttpTransactionFactory, // Close currently active sockets so that fresh page loads will not use any // recycled connections. For sockets currently in use, they may not close // immediately, but they will not be reusable. This is for debugging. - void CloseCurrentConnections(); + void CloseAllConnections(); // HttpTransactionFactory implementation: virtual int CreateTransaction(scoped_ptr<HttpTransaction>* trans); diff --git a/net/http/http_network_layer.cc b/net/http/http_network_layer.cc index e979ad0..0fb1050 100644 --- a/net/http/http_network_layer.cc +++ b/net/http/http_network_layer.cc @@ -156,7 +156,7 @@ void HttpNetworkLayer::Suspend(bool suspend) { suspended_ = suspend; if (suspend && session_) - session_->tcp_socket_pool()->CloseIdleSockets(); + session_->CloseIdleConnections(); } } // namespace net diff --git a/net/http/http_network_session.cc b/net/http/http_network_session.cc index b50b6e9..e67390c 100644 --- a/net/http/http_network_session.cc +++ b/net/http/http_network_session.cc @@ -6,13 +6,16 @@ #include <utility> +#include "base/compiler_specific.h" #include "base/logging.h" #include "base/stl_util-inl.h" #include "base/string_util.h" #include "base/values.h" #include "net/http/http_auth_handler_factory.h" #include "net/http/http_response_body_drainer.h" +#include "net/http/http_stream_factory_impl.h" #include "net/http/url_security_manager.h" +#include "net/proxy/proxy_service.h" #include "net/socket/client_socket_factory.h" #include "net/spdy/spdy_session_pool.h" @@ -20,7 +23,10 @@ namespace net { // TODO(mbelshe): Move the socket factories into HttpStreamFactory. HttpNetworkSession::HttpNetworkSession(const Params& params) - : cert_verifier_(NULL), + : net_log_(params.net_log), + network_delegate_(params.network_delegate), + cert_verifier_(params.cert_verifier), + http_auth_handler_factory_(params.http_auth_handler_factory), proxy_service_(params.proxy_service), ssl_config_service_(params.ssl_config_service), socket_pool_manager_(params.net_log, @@ -35,9 +41,8 @@ HttpNetworkSession::HttpNetworkSession(const Params& params) params.proxy_service, params.ssl_config_service), spdy_session_pool_(params.ssl_config_service), - http_auth_handler_factory_(params.http_auth_handler_factory), - network_delegate_(params.network_delegate), - net_log_(params.net_log) { + ALLOW_THIS_IN_INITIALIZER_LIST(http_stream_factory_( + new HttpStreamFactoryImpl(this))) { DCHECK(params.proxy_service); DCHECK(params.ssl_config_service); } diff --git a/net/http/http_network_session.h b/net/http/http_network_session.h index 36cb652..5c8f705 100644 --- a/net/http/http_network_session.h +++ b/net/http/http_network_session.h @@ -71,7 +71,7 @@ class HttpNetworkSession : public base::RefCounted<HttpNetworkSession>, explicit HttpNetworkSession(const Params& params); - HttpAuthCache* auth_cache() { return &auth_cache_; } + HttpAuthCache* http_auth_cache() { return &http_auth_cache_; } SSLClientAuthCache* ssl_client_auth_cache() { return &ssl_client_auth_cache_; } @@ -87,14 +87,6 @@ class HttpNetworkSession : public base::RefCounted<HttpNetworkSession>, return &alternate_protocols_; } - // Access to the SpdySettingsStorage - const SpdySettingsStorage& spdy_settings() const { - return spdy_settings_; - } - SpdySettingsStorage* mutable_spdy_settings() { - return &spdy_settings_; - } - TCPClientSocketPool* tcp_socket_pool() { return socket_pool_manager_.tcp_socket_pool(); } @@ -130,7 +122,7 @@ class HttpNetworkSession : public base::RefCounted<HttpNetworkSession>, } HttpStreamFactory* http_stream_factory() { - return &http_stream_factory_; + return http_stream_factory_.get(); } NetLog* net_log() { @@ -147,30 +139,37 @@ class HttpNetworkSession : public base::RefCounted<HttpNetworkSession>, // responsible for deleting the returned value. Value* SpdySessionPoolInfoToValue() const; - void FlushSocketPools() { + void CloseAllConnections() { socket_pool_manager_.FlushSocketPools(); + spdy_session_pool_.CloseCurrentSessions(); + } + + void CloseIdleConnections() { + socket_pool_manager_.CloseIdleSockets(); } + private: friend class base::RefCounted<HttpNetworkSession>; friend class HttpNetworkSessionPeer; ~HttpNetworkSession(); - HttpAuthCache auth_cache_; - SSLClientAuthCache ssl_client_auth_cache_; - HttpAlternateProtocols alternate_protocols_; - CertVerifier* cert_verifier_; + NetLog* const net_log_; + HttpNetworkDelegate* const network_delegate_; + CertVerifier* const cert_verifier_; + HttpAuthHandlerFactory* const http_auth_handler_factory_; + // Not const since it's modified by HttpNetworkSessionPeer for testing. scoped_refptr<ProxyService> proxy_service_; const scoped_refptr<SSLConfigService> ssl_config_service_; + + HttpAuthCache http_auth_cache_; + SSLClientAuthCache ssl_client_auth_cache_; + HttpAlternateProtocols alternate_protocols_; ClientSocketPoolManager socket_pool_manager_; SpdySessionPool spdy_session_pool_; - HttpStreamFactory http_stream_factory_; - HttpAuthHandlerFactory* const http_auth_handler_factory_; - HttpNetworkDelegate* const network_delegate_; - NetLog* const net_log_; - SpdySettingsStorage spdy_settings_; + scoped_ptr<HttpStreamFactory> http_stream_factory_; std::set<HttpResponseBodyDrainer*> response_drainers_; }; diff --git a/net/http/http_network_session_peer.cc b/net/http/http_network_session_peer.cc index 7bb342c..2ed3e76 100644 --- a/net/http/http_network_session_peer.cc +++ b/net/http/http_network_session_peer.cc @@ -6,6 +6,7 @@ #include "net/http/http_network_session.h" #include "net/http/http_proxy_client_socket_pool.h" +#include "net/proxy/proxy_service.h" #include "net/socket/socks_client_socket_pool.h" #include "net/socket/ssl_client_socket_pool.h" #include "net/socket/tcp_client_socket_pool.h" @@ -66,4 +67,9 @@ void HttpNetworkSessionPeer::SetProxyService(ProxyService* proxy_service) { session_->proxy_service_ = proxy_service; } +void HttpNetworkSessionPeer::SetHttpStreamFactory( + HttpStreamFactory* http_stream_factory) { + session_->http_stream_factory_.reset(http_stream_factory); +} + } // namespace net diff --git a/net/http/http_network_session_peer.h b/net/http/http_network_session_peer.h index 398488b..06101ca 100644 --- a/net/http/http_network_session_peer.h +++ b/net/http/http_network_session_peer.h @@ -13,6 +13,7 @@ namespace net { class HostPortPair; class HttpNetworkSession; class HttpProxyClientSocketPool; +class HttpStreamFactory; class ProxyService; class SOCKSClientSocketPool; class SSLClientSocketPool; @@ -42,6 +43,8 @@ class HttpNetworkSessionPeer { void SetProxyService(ProxyService* proxy_service); + void SetHttpStreamFactory(HttpStreamFactory* http_stream_factory); + private: const scoped_refptr<HttpNetworkSession> session_; diff --git a/net/http/http_network_transaction.cc b/net/http/http_network_transaction.cc index 128497f..98b9cd7 100644 --- a/net/http/http_network_transaction.cc +++ b/net/http/http_network_transaction.cc @@ -42,7 +42,7 @@ #include "net/http/http_response_body_drainer.h" #include "net/http/http_response_headers.h" #include "net/http/http_response_info.h" -#include "net/http/http_stream_request.h" +#include "net/http/http_stream_factory.h" #include "net/http/http_util.h" #include "net/http/url_security_manager.h" #include "net/socket/client_socket_factory.h" @@ -359,11 +359,15 @@ uint64 HttpNetworkTransaction::GetUploadProgress() const { return stream_->GetUploadProgress(); } -void HttpNetworkTransaction::OnStreamReady(HttpStream* stream) { +void HttpNetworkTransaction::OnStreamReady(const SSLConfig& used_ssl_config, + const ProxyInfo& used_proxy_info, + HttpStream* stream) { DCHECK_EQ(STATE_CREATE_STREAM_COMPLETE, next_state_); DCHECK(stream_request_.get()); stream_.reset(stream); + ssl_config_ = used_ssl_config; + proxy_info_ = used_proxy_info; response_.was_alternate_protocol_available = stream_request_->was_alternate_protocol_available(); response_.was_npn_negotiated = stream_request_->was_npn_negotiated(); @@ -373,23 +377,28 @@ void HttpNetworkTransaction::OnStreamReady(HttpStream* stream) { OnIOComplete(OK); } -void HttpNetworkTransaction::OnStreamFailed(int result) { +void HttpNetworkTransaction::OnStreamFailed(int result, + const SSLConfig& used_ssl_config) { DCHECK_EQ(STATE_CREATE_STREAM_COMPLETE, next_state_); DCHECK_NE(OK, result); DCHECK(stream_request_.get()); DCHECK(!stream_.get()); + ssl_config_ = used_ssl_config; OnIOComplete(result); } -void HttpNetworkTransaction::OnCertificateError(int result, - const SSLInfo& ssl_info) { +void HttpNetworkTransaction::OnCertificateError( + int result, + const SSLConfig& used_ssl_config, + const SSLInfo& ssl_info) { DCHECK_EQ(STATE_CREATE_STREAM_COMPLETE, next_state_); DCHECK_NE(OK, result); DCHECK(stream_request_.get()); DCHECK(!stream_.get()); response_.ssl_info = ssl_info; + ssl_config_ = used_ssl_config; // TODO(mbelshe): For now, we're going to pass the error through, and that // will close the stream_request in all cases. This means that we're always @@ -402,6 +411,8 @@ void HttpNetworkTransaction::OnCertificateError(int result, void HttpNetworkTransaction::OnNeedsProxyAuth( const HttpResponseInfo& proxy_response, + const SSLConfig& used_ssl_config, + const ProxyInfo& used_proxy_info, HttpAuthController* auth_controller) { DCHECK(stream_request_.get()); DCHECK_EQ(STATE_CREATE_STREAM_COMPLETE, next_state_); @@ -410,6 +421,8 @@ void HttpNetworkTransaction::OnNeedsProxyAuth( response_.headers = proxy_response.headers; response_.auth_challenge = proxy_response.auth_challenge; headers_valid_ = true; + ssl_config_ = used_ssl_config; + proxy_info_ = used_proxy_info; auth_controllers_[HttpAuth::AUTH_PROXY] = auth_controller; pending_auth_target_ = HttpAuth::AUTH_PROXY; @@ -418,20 +431,26 @@ void HttpNetworkTransaction::OnNeedsProxyAuth( } void HttpNetworkTransaction::OnNeedsClientAuth( + const SSLConfig& used_ssl_config, SSLCertRequestInfo* cert_info) { DCHECK_EQ(STATE_CREATE_STREAM_COMPLETE, next_state_); + ssl_config_ = used_ssl_config; response_.cert_request_info = cert_info; OnIOComplete(ERR_SSL_CLIENT_AUTH_CERT_NEEDED); } void HttpNetworkTransaction::OnHttpsProxyTunnelResponse( const HttpResponseInfo& response_info, + const SSLConfig& used_ssl_config, + const ProxyInfo& used_proxy_info, HttpStream* stream) { DCHECK_EQ(STATE_CREATE_STREAM_COMPLETE, next_state_); headers_valid_ = true; response_ = response_info; + ssl_config_ = used_ssl_config; + proxy_info_ = used_proxy_info; stream_.reset(stream); stream_request_.reset(); // we're done with the stream request OnIOComplete(ERR_HTTPS_PROXY_TUNNEL_RESPONSE); @@ -549,10 +568,8 @@ int HttpNetworkTransaction::DoCreateStream() { stream_request_.reset( session_->http_stream_factory()->RequestStream( - request_, - &ssl_config_, - &proxy_info_, - session_, + *request_, + ssl_config_, this, net_log_)); DCHECK(stream_request_.get()); @@ -609,7 +626,7 @@ int HttpNetworkTransaction::DoGenerateProxyAuthToken() { auth_controllers_[target] = new HttpAuthController(target, AuthURL(target), - session_->auth_cache(), + session_->http_auth_cache(), session_->http_auth_handler_factory()); return auth_controllers_[target]->MaybeGenerateAuthToken(request_, &io_callback_, @@ -630,7 +647,7 @@ int HttpNetworkTransaction::DoGenerateServerAuthToken() { auth_controllers_[target] = new HttpAuthController(target, AuthURL(target), - session_->auth_cache(), + session_->http_auth_cache(), session_->http_auth_handler_factory()); if (!ShouldApplyServerAuth()) return OK; diff --git a/net/http/http_network_transaction.h b/net/http/http_network_transaction.h index 66b6b29..3cec010 100644 --- a/net/http/http_network_transaction.h +++ b/net/http/http_network_transaction.h @@ -19,8 +19,8 @@ #include "net/http/http_auth.h" #include "net/http/http_request_headers.h" #include "net/http/http_response_info.h" +#include "net/http/http_stream_factory.h" #include "net/http/http_transaction.h" -#include "net/http/stream_factory.h" #include "net/proxy/proxy_service.h" namespace net { @@ -33,7 +33,7 @@ class IOBuffer; struct HttpRequestInfo; class HttpNetworkTransaction : public HttpTransaction, - public StreamRequest::Delegate { + public HttpStreamRequest::Delegate { public: explicit HttpNetworkTransaction(HttpNetworkSession* session); @@ -57,15 +57,25 @@ class HttpNetworkTransaction : public HttpTransaction, virtual LoadState GetLoadState() const; virtual uint64 GetUploadProgress() const; - // StreamRequest::Delegate methods: - virtual void OnStreamReady(HttpStream* stream); - virtual void OnStreamFailed(int status); - virtual void OnCertificateError(int status, const SSLInfo& ssl_info); + // HttpStreamRequest::Delegate methods: + virtual void OnStreamReady(const SSLConfig& used_ssl_config, + const ProxyInfo& used_proxy_info, + HttpStream* stream); + virtual void OnStreamFailed(int status, + const SSLConfig& used_ssl_config); + virtual void OnCertificateError(int status, + const SSLConfig& used_ssl_config, + const SSLInfo& ssl_info); virtual void OnNeedsProxyAuth( const HttpResponseInfo& response_info, + const SSLConfig& used_ssl_config, + const ProxyInfo& used_proxy_info, HttpAuthController* auth_controller); - virtual void OnNeedsClientAuth(SSLCertRequestInfo* cert_info); + virtual void OnNeedsClientAuth(const SSLConfig& used_ssl_config, + SSLCertRequestInfo* cert_info); virtual void OnHttpsProxyTunnelResponse(const HttpResponseInfo& response_info, + const SSLConfig& used_ssl_config, + const ProxyInfo& used_proxy_info, HttpStream* stream); private: @@ -215,9 +225,10 @@ class HttpNetworkTransaction : public HttpTransaction, const HttpRequestInfo* request_; HttpResponseInfo response_; + // |proxy_info_| is the ProxyInfo used by the HttpStreamRequest. ProxyInfo proxy_info_; - scoped_ptr<StreamRequest> stream_request_; + scoped_ptr<HttpStreamRequest> stream_request_; scoped_ptr<HttpStream> stream_; // True if we've validated the headers that the stream parser has returned. diff --git a/net/http/http_network_transaction_unittest.cc b/net/http/http_network_transaction_unittest.cc index e54edf5..ecd6132 100644 --- a/net/http/http_network_transaction_unittest.cc +++ b/net/http/http_network_transaction_unittest.cc @@ -1581,7 +1581,7 @@ TEST_F(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAlive) { EXPECT_TRUE(response->auth_challenge.get() == NULL); trans.reset(); - session->FlushSocketPools(); + session->CloseAllConnections(); } // Test the request-challenge-retry sequence for basic auth, over a keep-alive @@ -1695,7 +1695,7 @@ TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAlive) { // Flush the idle socket before the NetLog and HttpNetworkTransaction go // out of scope. - session->FlushSocketPools(); + session->CloseAllConnections(); } // Test that we don't read the response body when we fail to establish a tunnel, @@ -1753,7 +1753,7 @@ TEST_F(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) { EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv); // Flush the idle socket before the HttpNetworkTransaction goes out of scope. - session->FlushSocketPools(); + session->CloseAllConnections(); } // Test when a server (non-proxy) returns a 407 (proxy-authenticate). @@ -6923,8 +6923,7 @@ TEST_F(HttpNetworkTransactionTest, HostPortPair host_port_pair("www.google.com", 443); HostPortProxyPair pair(host_port_pair, ProxyServer::Direct()); scoped_refptr<SpdySession> spdy_session = - session->spdy_session_pool()->Get(pair, session->mutable_spdy_settings(), - BoundNetLog()); + session->spdy_session_pool()->Get(pair, BoundNetLog()); scoped_refptr<TCPSocketParams> tcp_params( new TCPSocketParams("www.google.com", 443, MEDIUM, GURL(), false)); @@ -8167,8 +8166,7 @@ TEST_F(HttpNetworkTransactionTest, PreconnectWithExistingSpdySession) { HostPortPair host_port_pair("www.google.com", 443); HostPortProxyPair pair(host_port_pair, ProxyServer::Direct()); scoped_refptr<SpdySession> spdy_session = - session->spdy_session_pool()->Get(pair, session->mutable_spdy_settings(), - BoundNetLog()); + session->spdy_session_pool()->Get(pair, BoundNetLog()); scoped_refptr<TCPSocketParams> tcp_params( new TCPSocketParams("www.google.com", 443, MEDIUM, GURL(), false)); TestCompletionCallback callback; diff --git a/net/http/http_proxy_client_socket_pool.cc b/net/http/http_proxy_client_socket_pool.cc index 3129133..13d6286 100644 --- a/net/http/http_proxy_client_socket_pool.cc +++ b/net/http/http_proxy_client_socket_pool.cc @@ -36,12 +36,10 @@ HttpProxySocketParams::HttpProxySocketParams( HttpAuthCache* http_auth_cache, HttpAuthHandlerFactory* http_auth_handler_factory, SpdySessionPool* spdy_session_pool, - SpdySettingsStorage* spdy_settings, bool tunnel) : tcp_params_(tcp_params), ssl_params_(ssl_params), spdy_session_pool_(spdy_session_pool), - spdy_settings_(spdy_settings), request_url_(request_url), user_agent_(user_agent), endpoint_(endpoint), @@ -291,11 +289,11 @@ int HttpProxyConnectJob::DoSpdyProxyCreateStream() { transport_socket_handle_->socket()->Disconnect(); transport_socket_handle_->Reset(); } - spdy_session = spdy_pool->Get(pair, params_->spdy_settings(), net_log()); + spdy_session = spdy_pool->Get(pair, net_log()); } else { // Create a session direct to the proxy itself int rv = spdy_pool->GetSpdySessionFromSocket( - pair, params_->spdy_settings(), transport_socket_handle_.release(), + pair, transport_socket_handle_.release(), net_log(), OK, &spdy_session, /*using_ssl_*/ true); if (rv < 0) return rv; diff --git a/net/http/http_proxy_client_socket_pool.h b/net/http/http_proxy_client_socket_pool.h index 4757b27..4ae07cf 100644 --- a/net/http/http_proxy_client_socket_pool.h +++ b/net/http/http_proxy_client_socket_pool.h @@ -28,7 +28,6 @@ class HttpAuthHandlerFactory; class SSLClientSocketPool; class SSLSocketParams; class SpdySessionPool; -class SpdySettingsStorage; class SpdyStream; class TCPClientSocketPool; class TCPSocketParams; @@ -47,7 +46,6 @@ class HttpProxySocketParams : public base::RefCounted<HttpProxySocketParams> { HttpAuthCache* http_auth_cache, HttpAuthHandlerFactory* http_auth_handler_factory, SpdySessionPool* spdy_session_pool, - SpdySettingsStorage* spdy_settings, bool tunnel); const scoped_refptr<TCPSocketParams>& tcp_params() const { @@ -66,9 +64,6 @@ class HttpProxySocketParams : public base::RefCounted<HttpProxySocketParams> { SpdySessionPool* spdy_session_pool() { return spdy_session_pool_; } - SpdySettingsStorage* spdy_settings() { - return spdy_settings_; - } const HostResolver::RequestInfo& destination() const; bool tunnel() const { return tunnel_; } @@ -79,7 +74,6 @@ class HttpProxySocketParams : public base::RefCounted<HttpProxySocketParams> { const scoped_refptr<TCPSocketParams> tcp_params_; const scoped_refptr<SSLSocketParams> ssl_params_; SpdySessionPool* spdy_session_pool_; - SpdySettingsStorage* spdy_settings_; const GURL request_url_; const std::string user_agent_; const HostPortPair endpoint_; diff --git a/net/http/http_proxy_client_socket_pool_unittest.cc b/net/http/http_proxy_client_socket_pool_unittest.cc index 359a058..5830b3a7 100644 --- a/net/http/http_proxy_client_socket_pool_unittest.cc +++ b/net/http/http_proxy_client_socket_pool_unittest.cc @@ -94,13 +94,13 @@ class HttpProxyClientSocketPoolTest : public TestWithHttpParam { void AddAuthToCache() { const string16 kFoo(ASCIIToUTF16("foo")); const string16 kBar(ASCIIToUTF16("bar")); - session_->auth_cache()->Add(GURL("http://proxy/"), - "MyRealm1", - HttpAuth::AUTH_SCHEME_BASIC, - "Basic realm=MyRealm1", - kFoo, - kBar, - "/"); + session_->http_auth_cache()->Add(GURL("http://proxy/"), + "MyRealm1", + HttpAuth::AUTH_SCHEME_BASIC, + "Basic realm=MyRealm1", + kFoo, + kBar, + "/"); } scoped_refptr<TCPSocketParams> GetTcpParams() { @@ -125,10 +125,9 @@ class HttpProxyClientSocketPoolTest : public TestWithHttpParam { GURL(tunnel ? "https://www.google.com/" : "http://www.google.com"), "", HostPortPair("www.google.com", tunnel ? 443 : 80), - session_->auth_cache(), + session_->http_auth_cache(), session_->http_auth_handler_factory(), session_->spdy_session_pool(), - session_->mutable_spdy_settings(), tunnel)); } diff --git a/net/http/http_stream_factory.cc b/net/http/http_stream_factory.cc index 4673d58..9189e99 100644 --- a/net/http/http_stream_factory.cc +++ b/net/http/http_stream_factory.cc @@ -1,17 +1,16 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "net/http/http_stream_factory.h" -#include "base/stl_util-inl.h" +#include "base/logging.h" #include "base/string_number_conversions.h" #include "base/string_split.h" -#include "base/string_util.h" -#include "net/base/net_log.h" -#include "net/base/net_util.h" -#include "net/http/http_network_session.h" -#include "net/http/http_stream_request.h" +#include "googleurl/src/gurl.h" +#include "net/base/host_mapping_rules.h" +#include "net/base/host_port_pair.h" +#include "net/http/http_alternate_protocols.h" namespace net { @@ -32,62 +31,7 @@ std::list<HostPortPair>* HttpStreamFactory::forced_spdy_exclusions_ = NULL; // static bool HttpStreamFactory::ignore_certificate_errors_ = false; -HttpStreamFactory::HttpStreamFactory() { -} - -HttpStreamFactory::~HttpStreamFactory() { - RequestCallbackMap request_callback_map; - request_callback_map.swap(request_callback_map_); - for (RequestCallbackMap::iterator it = request_callback_map.begin(); - it != request_callback_map.end(); ++it) { - delete it->first; - // We don't invoke the callback in the destructor. - } -} - -// static -void HttpStreamFactory::SetHostMappingRules(const std::string& rules) { - HostMappingRules* host_mapping_rules = new HostMappingRules(); - host_mapping_rules->SetRulesFromString(rules); - delete host_mapping_rules_; - host_mapping_rules_ = host_mapping_rules; -} - -StreamRequest* HttpStreamFactory::RequestStream( - const HttpRequestInfo* request_info, - SSLConfig* ssl_config, - ProxyInfo* proxy_info, - HttpNetworkSession* session, - StreamRequest::Delegate* delegate, - const BoundNetLog& net_log) { - HttpStreamRequest* stream = new HttpStreamRequest(this, session); - stream->Start(request_info, ssl_config, proxy_info, delegate, net_log); - return stream; -} - -int HttpStreamFactory::PreconnectStreams( - int num_streams, - const HttpRequestInfo* request_info, - SSLConfig* ssl_config, - ProxyInfo* proxy_info, - HttpNetworkSession* session, - const BoundNetLog& net_log, - CompletionCallback* callback) { - HttpStreamRequest* stream = new HttpStreamRequest(this, session); - int rv = stream->Preconnect(num_streams, request_info, ssl_config, - proxy_info, this, net_log); - DCHECK_EQ(ERR_IO_PENDING, rv); - request_callback_map_[stream] = callback; - return rv; -} - -void HttpStreamFactory::AddTLSIntolerantServer(const GURL& url) { - tls_intolerant_servers_.insert(GetHostAndPort(url)); -} - -bool HttpStreamFactory::IsTLSIntolerantServer(const GURL& url) { - return ContainsKey(tls_intolerant_servers_, GetHostAndPort(url)); -} +HttpStreamFactory::~HttpStreamFactory() {} void HttpStreamFactory::ProcessAlternateProtocol( HttpAlternateProtocols* alternate_protocols, @@ -128,8 +72,7 @@ void HttpStreamFactory::ProcessAlternateProtocol( } HostPortPair host_port(http_host_port_pair); - if (host_mapping_rules_) - host_mapping_rules_->RewriteHost(&host_port); + host_mapping_rules().RewriteHost(&host_port); if (alternate_protocols->HasAlternateProtocolFor(host_port)) { const HttpAlternateProtocols::PortProtocolPair existing_alternate = @@ -144,7 +87,7 @@ void HttpStreamFactory::ProcessAlternateProtocol( GURL HttpStreamFactory::ApplyHostMappingRules(const GURL& url, HostPortPair* endpoint) { - if (host_mapping_rules_ && host_mapping_rules_->RewriteHost(endpoint)) { + if (host_mapping_rules().RewriteHost(endpoint)) { url_canon::Replacements<char> replacements; const std::string port_str = base::IntToString(endpoint->port()); replacements.SetPort(port_str.c_str(), @@ -156,15 +99,29 @@ GURL HttpStreamFactory::ApplyHostMappingRules(const GURL& url, return url; } -void HttpStreamFactory::OnPreconnectsComplete( - HttpStreamRequest* request, int result) { - RequestCallbackMap::iterator it = request_callback_map_.find(request); - DCHECK(it != request_callback_map_.end()); - CompletionCallback* callback = it->second; - request_callback_map_.erase(it); - delete request; - callback->Run(result); +// static +void HttpStreamFactory::add_forced_spdy_exclusion(const std::string& value) { + HostPortPair pair = HostPortPair::FromURL(GURL(value)); + if (!forced_spdy_exclusions_) + forced_spdy_exclusions_ = new std::list<HostPortPair>(); + forced_spdy_exclusions_->push_back(pair); } -} // namespace net +// static +void HttpStreamFactory::SetHostMappingRules(const std::string& rules) { + HostMappingRules* host_mapping_rules = new HostMappingRules; + host_mapping_rules->SetRulesFromString(rules); + delete host_mapping_rules_; + host_mapping_rules_ = host_mapping_rules; +} + +HttpStreamFactory::HttpStreamFactory() {} +// static +const HostMappingRules& HttpStreamFactory::host_mapping_rules() { + if (!host_mapping_rules_) + host_mapping_rules_ = new HostMappingRules; + return *host_mapping_rules_; +} + +} // namespace net diff --git a/net/http/http_stream_factory.h b/net/http/http_stream_factory.h index 97bd79c..3d3bada 100644 --- a/net/http/http_stream_factory.h +++ b/net/http/http_stream_factory.h @@ -6,35 +6,176 @@ #define NET_HTTP_HTTP_STREAM_FACTORY_H_ #include <list> -#include <map> -#include <set> #include <string> -#include "base/scoped_ptr.h" +#include "base/string16.h" +#include "base/ref_counted.h" #include "net/base/completion_callback.h" -#include "net/base/host_mapping_rules.h" -#include "net/base/host_port_pair.h" -#include "net/base/ssl_config_service.h" -#include "net/http/http_auth.h" -#include "net/http/http_auth_controller.h" -#include "net/http/http_stream_request.h" -#include "net/http/stream_factory.h" -#include "net/proxy/proxy_service.h" -#include "net/socket/client_socket_handle.h" +#include "net/base/load_states.h" + +class GURL; namespace net { +class BoundNetLog; +class HostMappingRules; +class HostPortPair; +class HttpAlternateProtocols; +class HttpAuthController; class HttpNetworkSession; +class HttpResponseInfo; +class HttpStream; +class ProxyInfo; +class SSLCertRequestInfo; +class SSLInfo; +class X509Certificate; struct HttpRequestInfo; -class HttpStreamRequest; +struct SSLConfig; + +// The HttpStreamRequest is the client's handle to the worker object which +// handles the creation of an HttpStream. While the HttpStream is being +// created, this object is the creator's handle for interacting with the +// HttpStream creation process. The request is cancelled by deleting it, after +// which no callbacks will be invoked. +class HttpStreamRequest { + public: + // The HttpStreamRequest::Delegate is a set of callback methods for a + // HttpStreamRequestJob. Generally, only one of these methods will be + // called as a result of a stream request. + class Delegate { + public: + virtual ~Delegate() {} + + // This is the success case. + // |stream| is now owned by the delegate. + // |used_ssl_config| indicates the actual SSL configuration used for this + // stream, since the HttpStreamRequest may have modified the configuration + // during stream processing. + // |used_proxy_info| indicates the actual ProxyInfo used for this stream, + // since the HttpStreamRequest performs the proxy resolution. + virtual void OnStreamReady( + const SSLConfig& used_ssl_config, + const ProxyInfo& used_proxy_info, + HttpStream* stream) = 0; + + // This is the failure to create a stream case. + // |used_ssl_config| indicates the actual SSL configuration used for this + // stream, since the HttpStreamRequest may have modified the configuration + // during stream processing. + virtual void OnStreamFailed(int status, + const SSLConfig& used_ssl_config) = 0; + + // Called when we have a certificate error for the request. + // |used_ssl_config| indicates the actual SSL configuration used for this + // stream, since the HttpStreamRequest may have modified the configuration + // during stream processing. + virtual void OnCertificateError(int status, + const SSLConfig& used_ssl_config, + const SSLInfo& ssl_info) = 0; + + // This is the failure case where we need proxy authentication during + // proxy tunnel establishment. For the tunnel case, we were unable to + // create the HttpStream, so the caller provides the auth and then resumes + // the HttpStreamRequest. + // + // For the non-tunnel case, the caller will discover the authentication + // failure when reading response headers. At that point, he will handle the + // authentication failure and restart the HttpStreamRequest entirely. + // + // Ownership of |auth_controller| and |proxy_response| are owned + // by the HttpStreamRequest. |proxy_response| is not guaranteed to be usable + // after the lifetime of this callback. The delegate may take a reference + // to |auth_controller| if it is needed beyond the lifetime of this + // callback. + // + // |used_ssl_config| indicates the actual SSL configuration used for this + // stream, since the HttpStreamRequest may have modified the configuration + // during stream processing. + virtual void OnNeedsProxyAuth(const HttpResponseInfo& proxy_response, + const SSLConfig& used_ssl_config, + const ProxyInfo& used_proxy_info, + HttpAuthController* auth_controller) = 0; + + // This is the failure for SSL Client Auth + // Ownership of |cert_info| is retained by the HttpStreamRequest. The + // delegate may take a reference if it needs the cert_info beyond the + // lifetime of this callback. + virtual void OnNeedsClientAuth(const SSLConfig& used_ssl_config, + SSLCertRequestInfo* cert_info) = 0; + + // This is the failure of the CONNECT request through an HTTPS proxy. + // Headers can be read from |response_info|, while the body can be read + // from |stream|. + // + // |used_ssl_config| indicates the actual SSL configuration used for this + // stream, since the HttpStreamRequest may have modified the configuration + // during stream processing. + // + // |used_proxy_info| indicates the actual ProxyInfo used for this stream, + // since the HttpStreamRequest performs the proxy resolution. + // + // Ownership of |stream| is transferred to the delegate. + virtual void OnHttpsProxyTunnelResponse( + const HttpResponseInfo& response_info, + const SSLConfig& used_ssl_config, + const ProxyInfo& used_proxy_info, + HttpStream* stream) = 0; + }; + + virtual ~HttpStreamRequest() {} + + // When a HttpStream creation process is stalled due to necessity + // of Proxy authentication credentials, the delegate OnNeedsProxyAuth + // will have been called. It now becomes the delegate's responsibility + // to collect the necessary credentials, and then call this method to + // resume the HttpStream creation process. + virtual int RestartTunnelWithProxyAuth(const string16& username, + const string16& password) = 0; + + // Returns the LoadState for the request. + virtual LoadState GetLoadState() const = 0; + + // Returns true if an AlternateProtocol for this request was available. + virtual bool was_alternate_protocol_available() const = 0; + + // Returns true if TLS/NPN was negotiated for this stream. + virtual bool was_npn_negotiated() const = 0; + + // Returns true if this stream is being fetched over SPDY. + virtual bool using_spdy() const = 0; +}; -class HttpStreamFactory : public StreamFactory, - public HttpStreamRequest::PreconnectDelegate { +// The HttpStreamFactory defines an interface for creating usable HttpStreams. +class HttpStreamFactory { public: - HttpStreamFactory(); virtual ~HttpStreamFactory(); + void ProcessAlternateProtocol( + HttpAlternateProtocols* alternate_protocols, + const std::string& alternate_protocol_str, + const HostPortPair& http_host_port_pair); + + // Virtual interface methods. + + // Request a stream. + // Will callback to the HttpStreamRequestDelegate upon completion. + virtual HttpStreamRequest* RequestStream( + const HttpRequestInfo& info, + const SSLConfig& ssl_config, + HttpStreamRequest::Delegate* delegate, + const BoundNetLog& net_log) = 0; + + // Requests that enough connections for |num_streams| be opened. + virtual void PreconnectStreams(int num_streams, + const HttpRequestInfo& info, + const SSLConfig& ssl_config, + const BoundNetLog& net_log) = 0; + + virtual void AddTLSIntolerantServer(const GURL& url) = 0; + virtual bool IsTLSIntolerantServer(const GURL& url) const = 0; + // Static settings + static GURL ApplyHostMappingRules(const GURL& url, HostPortPair* endpoint); // Turns spdy on or off. static void set_spdy_enabled(bool value) { @@ -65,12 +206,7 @@ class HttpStreamFactory : public StreamFactory, static bool force_spdy_always() { return force_spdy_always_; } // Add a URL to exclude from forced SPDY. - static void add_forced_spdy_exclusion(const std::string& value) { - HostPortPair pair = HostPortPair::FromURL(GURL(value)); - if (!forced_spdy_exclusions_) - forced_spdy_exclusions_ = new std::list<HostPortPair>(); - forced_spdy_exclusions_->push_back(pair); - } + static void add_forced_spdy_exclusion(const std::string& value); static std::list<HostPortPair>* forced_spdy_exclusions() { return forced_spdy_exclusions_; } @@ -82,7 +218,7 @@ class HttpStreamFactory : public StreamFactory, } static const std::string* next_protos() { return next_protos_; } - // Sets the HttpStreamFactory into a mode where it can ignore certificate + // Sets the HttpStreamFactoryImpl into a mode where it can ignore certificate // errors. This is for testing. static void set_ignore_certificate_errors(bool value) { ignore_certificate_errors_ = value; @@ -93,35 +229,11 @@ class HttpStreamFactory : public StreamFactory, static void SetHostMappingRules(const std::string& rules); - // StreamFactory Interface - virtual StreamRequest* RequestStream(const HttpRequestInfo* info, - SSLConfig* ssl_config, - ProxyInfo* proxy_info, - HttpNetworkSession* session, - StreamRequest::Delegate* delegate, - const BoundNetLog& net_log); - virtual int PreconnectStreams(int num_streams, - const HttpRequestInfo* info, - SSLConfig* ssl_config, - ProxyInfo* proxy_info, - HttpNetworkSession* session, - const BoundNetLog& net_log, - CompletionCallback* callback); - virtual void AddTLSIntolerantServer(const GURL& url); - virtual bool IsTLSIntolerantServer(const GURL& url); - virtual void ProcessAlternateProtocol( - HttpAlternateProtocols* alternate_protocols, - const std::string& alternate_protocol_str, - const HostPortPair& http_host_port_pair); - virtual GURL ApplyHostMappingRules(const GURL& url, HostPortPair* endpoint); - - // HttpStreamRequest::PreconnectDelegate API - virtual void OnPreconnectsComplete(HttpStreamRequest* request, int result); + protected: + HttpStreamFactory(); private: - typedef std::map<HttpStreamRequest*, CompletionCallback*> RequestCallbackMap; - RequestCallbackMap request_callback_map_; - std::set<std::string> tls_intolerant_servers_; + static const HostMappingRules& host_mapping_rules(); static const HostMappingRules* host_mapping_rules_; static const std::string* next_protos_; @@ -138,4 +250,3 @@ class HttpStreamFactory : public StreamFactory, } // namespace net #endif // NET_HTTP_HTTP_STREAM_FACTORY_H_ - diff --git a/net/http/http_stream_factory_impl.cc b/net/http/http_stream_factory_impl.cc new file mode 100644 index 0000000..02dd29d --- /dev/null +++ b/net/http/http_stream_factory_impl.cc @@ -0,0 +1,299 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "net/http/http_stream_factory_impl.h" + +#include "base/stl_util-inl.h" +#include "net/base/net_log.h" +#include "net/base/net_util.h" +#include "net/http/http_network_session.h" +#include "net/http/http_stream_factory_impl_job.h" + +namespace net { + +class HttpStreamFactoryImpl::Request : public HttpStreamRequest { + public: + Request(HttpStreamFactoryImpl* factory, + HttpStreamRequest::Delegate* delegate); + virtual ~Request(); + + Job* job() const { return job_; } + + // Binds |job| to this request. + void BindJob(HttpStreamFactoryImpl::Job* job); + + // Marks completion of the request. Must be called before OnStreamReady(). + void Complete(bool was_alternate_protocol_available, + bool was_npn_negotiated, + bool using_spdy); + + // HttpStreamRequest::Delegate methods which we implement. Note we don't + // actually subclass HttpStreamRequest::Delegate. + + void OnStreamReady( + const SSLConfig& used_ssl_config, + const ProxyInfo& used_proxy_info, + HttpStream* stream); + void OnStreamFailed(int status, const SSLConfig& used_ssl_config); + void OnCertificateError(int status, + const SSLConfig& used_ssl_config, + const SSLInfo& ssl_info); + void OnNeedsProxyAuth(const HttpResponseInfo& proxy_response, + const SSLConfig& used_ssl_config, + const ProxyInfo& used_proxy_info, + HttpAuthController* auth_controller); + void OnNeedsClientAuth(const SSLConfig& used_ssl_config, + SSLCertRequestInfo* cert_info); + void OnHttpsProxyTunnelResponse( + const HttpResponseInfo& response_info, + const SSLConfig& used_ssl_config, + const ProxyInfo& used_proxy_info, + HttpStream* stream); + + // HttpStreamRequest methods. + + virtual int RestartTunnelWithProxyAuth(const string16& username, + const string16& password); + virtual LoadState GetLoadState() const; + virtual bool was_alternate_protocol_available() const; + virtual bool was_npn_negotiated() const; + virtual bool using_spdy() const; + + private: + HttpStreamFactoryImpl* const factory_; + HttpStreamRequest::Delegate* const delegate_; + + // The |job_| that this request is tied to. + // TODO(willchan): Revisit this when we decouple requests and jobs further. + HttpStreamFactoryImpl::Job* job_; + + bool completed_; + bool was_alternate_protocol_available_; + bool was_npn_negotiated_; + bool using_spdy_; + DISALLOW_COPY_AND_ASSIGN(Request); +}; + +HttpStreamFactoryImpl::Request::Request(HttpStreamFactoryImpl* factory, + HttpStreamRequest::Delegate* delegate) + : factory_(factory), + delegate_(delegate), + job_(NULL), + completed_(false), + was_alternate_protocol_available_(false), + was_npn_negotiated_(false), + using_spdy_(false) { + DCHECK(factory_); + DCHECK(delegate_); +} + +HttpStreamFactoryImpl::Request::~Request() { + factory_->request_map_.erase(job_); + + // TODO(willchan): Remove this when we decouple requests and jobs. + delete job_; +} + +void HttpStreamFactoryImpl::Request::BindJob(HttpStreamFactoryImpl::Job* job) { + DCHECK(job); + DCHECK(!job_); + job_ = job; +} + +void HttpStreamFactoryImpl::Request::Complete( + bool was_alternate_protocol_available, + bool was_npn_negotiated, + bool using_spdy) { + DCHECK(!completed_); + completed_ = true; + was_alternate_protocol_available_ = was_alternate_protocol_available; + was_npn_negotiated_ = was_npn_negotiated; + using_spdy_ = using_spdy; +} + +void HttpStreamFactoryImpl::Request::OnStreamReady( + const SSLConfig& used_ssl_config, + const ProxyInfo& used_proxy_info, + HttpStream* stream) { + DCHECK(stream); + DCHECK(completed_); + delegate_->OnStreamReady(used_ssl_config, used_proxy_info, stream); +} + +void HttpStreamFactoryImpl::Request::OnStreamFailed( + int status, + const SSLConfig& used_ssl_config) { + DCHECK_NE(OK, status); + delegate_->OnStreamFailed(status, used_ssl_config); +} + +void HttpStreamFactoryImpl::Request::OnCertificateError( + int status, + const SSLConfig& used_ssl_config, + const SSLInfo& ssl_info) { + DCHECK_NE(OK, status); + delegate_->OnCertificateError(status, used_ssl_config, ssl_info); +} + +void HttpStreamFactoryImpl::Request::OnNeedsProxyAuth( + const HttpResponseInfo& proxy_response, + const SSLConfig& used_ssl_config, + const ProxyInfo& used_proxy_info, + HttpAuthController* auth_controller) { + delegate_->OnNeedsProxyAuth( + proxy_response, used_ssl_config, used_proxy_info, auth_controller); +} + +void HttpStreamFactoryImpl::Request::OnNeedsClientAuth( + const SSLConfig& used_ssl_config, + SSLCertRequestInfo* cert_info) { + delegate_->OnNeedsClientAuth(used_ssl_config, cert_info); +} + +void HttpStreamFactoryImpl::Request::OnHttpsProxyTunnelResponse( + const HttpResponseInfo& response_info, + const SSLConfig& used_ssl_config, + const ProxyInfo& used_proxy_info, + HttpStream* stream) { + delegate_->OnHttpsProxyTunnelResponse( + response_info, used_ssl_config, used_proxy_info, stream); +} + +int HttpStreamFactoryImpl::Request::RestartTunnelWithProxyAuth( + const string16& username, + const string16& password) { + return job_->RestartTunnelWithProxyAuth(username, password); +} + +LoadState HttpStreamFactoryImpl::Request::GetLoadState() const { + return factory_->GetLoadState(*this); +} + +bool HttpStreamFactoryImpl::Request::was_alternate_protocol_available() const { + DCHECK(completed_); + return was_alternate_protocol_available_; +} + +bool HttpStreamFactoryImpl::Request::was_npn_negotiated() const { + DCHECK(completed_); + return was_npn_negotiated_; +} + +bool HttpStreamFactoryImpl::Request::using_spdy() const { + DCHECK(completed_); + return using_spdy_; +} + +HttpStreamFactoryImpl::HttpStreamFactoryImpl(HttpNetworkSession* session) + : session_(session) {} + +HttpStreamFactoryImpl::~HttpStreamFactoryImpl() { + DCHECK(request_map_.empty()); + + std::set<const Job*> tmp_job_set; + tmp_job_set.swap(preconnect_job_set_); + STLDeleteContainerPointers(tmp_job_set.begin(), tmp_job_set.end()); + DCHECK(preconnect_job_set_.empty()); +} + +HttpStreamRequest* HttpStreamFactoryImpl::RequestStream( + const HttpRequestInfo& request_info, + const SSLConfig& ssl_config, + HttpStreamRequest::Delegate* delegate, + const BoundNetLog& net_log) { + Job* job = new Job(this, session_); + Request* request = new Request(this, delegate); + request_map_[job] = request; + request->BindJob(job); + job->Start(request_info, ssl_config, net_log); + return request; +} + +void HttpStreamFactoryImpl::PreconnectStreams( + int num_streams, + const HttpRequestInfo& request_info, + const SSLConfig& ssl_config, + const BoundNetLog& net_log) { + Job* job = new Job(this, session_); + preconnect_job_set_.insert(job); + job->Preconnect(num_streams, request_info, ssl_config, net_log); +} + +void HttpStreamFactoryImpl::AddTLSIntolerantServer(const GURL& url) { + tls_intolerant_servers_.insert(GetHostAndPort(url)); +} + +bool HttpStreamFactoryImpl::IsTLSIntolerantServer(const GURL& url) const { + return ContainsKey(tls_intolerant_servers_, GetHostAndPort(url)); +} + +LoadState HttpStreamFactoryImpl::GetLoadState(const Request& request) const { + // TODO(willchan): Will break when we do late binding. + return request.job()->GetLoadState(); +} + +void HttpStreamFactoryImpl::OnStreamReady(const Job* job, + const SSLConfig& ssl_config, + const ProxyInfo& proxy_info, + HttpStream* stream) { + DCHECK(ContainsKey(request_map_, job)); + Request* request = request_map_[job]; + request->Complete(job->was_alternate_protocol_available(), + job->was_npn_negotiated(), + job->using_spdy()); + request->OnStreamReady(ssl_config, proxy_info, stream); +} + +void HttpStreamFactoryImpl::OnStreamFailed(const Job* job, + int result, + const SSLConfig& ssl_config) { + DCHECK(ContainsKey(request_map_, job)); + request_map_[job]->OnStreamFailed(result, ssl_config); +} + +void HttpStreamFactoryImpl::OnCertificateError(const Job* job, + int result, + const SSLConfig& ssl_config, + const SSLInfo& ssl_info) { + DCHECK(ContainsKey(request_map_, job)); + request_map_[job]->OnCertificateError(result, ssl_config, ssl_info); +} + +void HttpStreamFactoryImpl::OnNeedsProxyAuth( + const Job* job, + const HttpResponseInfo& response, + const SSLConfig& ssl_config, + const ProxyInfo& proxy_info, + HttpAuthController* auth_controller) { + DCHECK(ContainsKey(request_map_, job)); + request_map_[job]->OnNeedsProxyAuth( + response, ssl_config, proxy_info, auth_controller); +} + +void HttpStreamFactoryImpl::OnNeedsClientAuth( + const Job* job, + const SSLConfig& ssl_config, + SSLCertRequestInfo* cert_info) { + DCHECK(ContainsKey(request_map_, job)); + request_map_[job]->OnNeedsClientAuth(ssl_config, cert_info); +} + +void HttpStreamFactoryImpl::OnHttpsProxyTunnelResponse( + const Job* job, + const HttpResponseInfo& response_info, + const SSLConfig& ssl_config, + const ProxyInfo& proxy_info, + HttpStream* stream) { + DCHECK(ContainsKey(request_map_, job)); + request_map_[job]->OnHttpsProxyTunnelResponse( + response_info, ssl_config, proxy_info, stream); +} + +void HttpStreamFactoryImpl::OnPreconnectsComplete(const Job* job) { + preconnect_job_set_.erase(job); + delete job; + OnPreconnectsCompleteInternal(); +} + +} // namespace net diff --git a/net/http/http_stream_factory_impl.h b/net/http/http_stream_factory_impl.h new file mode 100644 index 0000000..d86a8fa --- /dev/null +++ b/net/http/http_stream_factory_impl.h @@ -0,0 +1,94 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NET_HTTP_HTTP_STREAM_FACTORY_IMPL_H_ +#define NET_HTTP_HTTP_STREAM_FACTORY_IMPL_H_ + +#include <map> +#include <set> +#include <string> + +#include "net/http/http_stream_factory.h" + +namespace net { + +class HttpNetworkSession; + +class HttpStreamFactoryImpl : public HttpStreamFactory { + public: + explicit HttpStreamFactoryImpl(HttpNetworkSession* session); + virtual ~HttpStreamFactoryImpl(); + + // HttpStreamFactory Interface + virtual HttpStreamRequest* RequestStream( + const HttpRequestInfo& info, + const SSLConfig& ssl_config, + HttpStreamRequest::Delegate* delegate, + const BoundNetLog& net_log); + + virtual void PreconnectStreams(int num_streams, + const HttpRequestInfo& info, + const SSLConfig& ssl_config, + const BoundNetLog& net_log); + virtual void AddTLSIntolerantServer(const GURL& url); + virtual bool IsTLSIntolerantServer(const GURL& url) const; + + private: + class Request; + class Job; + + LoadState GetLoadState(const Request& request) const; + + void OnStreamReady(const Job* job, + const SSLConfig& ssl_config, + const ProxyInfo& proxy_info, + HttpStream* stream); + void OnStreamFailed(const Job* job, int result, const SSLConfig& ssl_config); + void OnCertificateError(const Job* job, + int result, + const SSLConfig& ssl_config, + const SSLInfo& ssl_info); + void OnNeedsProxyAuth(const Job* job, + const HttpResponseInfo& response_info, + const SSLConfig& ssl_config, + const ProxyInfo& proxy_info, + HttpAuthController* auth_controller); + void OnNeedsClientAuth(const Job* job, + const SSLConfig& ssl_config, + SSLCertRequestInfo* cert_info); + void OnHttpsProxyTunnelResponse(const Job* job, + const HttpResponseInfo& response_info, + const SSLConfig& ssl_config, + const ProxyInfo& proxy_info, + HttpStream* stream); + + void OnPreconnectsComplete(const Job* job); + + // Called when the Preconnect completes. Used for testing. + virtual void OnPreconnectsCompleteInternal() {} + + HttpNetworkSession* const session_; + + std::set<std::string> tls_intolerant_servers_; + + // All Requests are handed out to clients. By the time HttpStreamFactoryImpl + // is destroyed, all Requests should be deleted (which should remove them from + // |request_map_|. + // TODO(willchan): Change to a different key when we enable late binding. This + // is the key part that keeps things tightly bound. + // Note that currently the Request assumes ownership of the Job. We will break + // this with late binding, and the factory will own the Job. + std::map<const Job*, Request*> request_map_; + + // These jobs correspond to preconnect requests and have no associated Request + // object. They're owned by HttpStreamFactoryImpl. Leftover jobs will be + // deleted when the factory is destroyed. + std::set<const Job*> preconnect_job_set_; + + DISALLOW_COPY_AND_ASSIGN(HttpStreamFactoryImpl); +}; + +} // namespace net + +#endif // NET_HTTP_HTTP_STREAM_FACTORY_IMPL_H_ diff --git a/net/http/http_stream_request.cc b/net/http/http_stream_factory_impl_job.cc index 4814e55..3f1968c 100644 --- a/net/http/http_stream_request.cc +++ b/net/http/http_stream_factory_impl_job.cc @@ -2,8 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "net/http/http_stream_request.h" +#include "net/http/http_stream_factory_impl_job.h" +#include "base/logging.h" #include "base/stl_util-inl.h" #include "base/string_number_conversions.h" #include "base/string_util.h" @@ -44,18 +45,12 @@ GURL UpgradeUrlToHttps(const GURL& original_url) { } // namespace -HttpStreamRequest::HttpStreamRequest( - StreamFactory* factory, - HttpNetworkSession* session) - : request_info_(NULL), - proxy_info_(NULL), - ssl_config_(NULL), - session_(session), - ALLOW_THIS_IN_INITIALIZER_LIST( - io_callback_(this, &HttpStreamRequest::OnIOComplete)), +HttpStreamFactoryImpl::Job::Job(HttpStreamFactoryImpl* stream_factory, + HttpNetworkSession* session) + : ALLOW_THIS_IN_INITIALIZER_LIST(io_callback_(this, &Job::OnIOComplete)), connection_(new ClientSocketHandle), - factory_(factory), - delegate_(NULL), + session_(session), + stream_factory_(stream_factory), next_state_(STATE_NONE), pac_request_(NULL), using_ssl_(false), @@ -67,7 +62,6 @@ HttpStreamRequest::HttpStreamRequest( establishing_tunnel_(false), was_alternate_protocol_available_(false), was_npn_negotiated_(false), - preconnect_delegate_(NULL), num_streams_(0), ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) { if (HttpStreamFactory::use_alternate_protocols()) @@ -76,7 +70,7 @@ HttpStreamRequest::HttpStreamRequest( alternate_protocol_mode_ = kDoNotUseAlternateProtocol; } -HttpStreamRequest::~HttpStreamRequest() { +HttpStreamFactoryImpl::Job::~Job() { // When we're in a partially constructed state, waiting for the user to // provide certificate handling information or authentication, we can't reuse // this stream at all. @@ -93,49 +87,30 @@ HttpStreamRequest::~HttpStreamRequest() { stream_->Close(true /* not reusable */); } -void HttpStreamRequest::Start(const HttpRequestInfo* request_info, - SSLConfig* ssl_config, - ProxyInfo* proxy_info, - Delegate* delegate, - const BoundNetLog& net_log) { - DCHECK(preconnect_delegate_ == NULL && delegate_ == NULL); - DCHECK(delegate); - delegate_ = delegate; - StartInternal(request_info, ssl_config, proxy_info, net_log); +void HttpStreamFactoryImpl::Job::Start(const HttpRequestInfo& request_info, + const SSLConfig& ssl_config, + const BoundNetLog& net_log) { + StartInternal(request_info, ssl_config, net_log); } -int HttpStreamRequest::Preconnect(int num_streams, - const HttpRequestInfo* request_info, - SSLConfig* ssl_config, - ProxyInfo* proxy_info, - PreconnectDelegate* delegate, - const BoundNetLog& net_log) { - DCHECK(preconnect_delegate_ == NULL && delegate_ == NULL); - DCHECK(delegate); +int HttpStreamFactoryImpl::Job::Preconnect(int num_streams, + const HttpRequestInfo& request_info, + const SSLConfig& ssl_config, + const BoundNetLog& net_log) { + DCHECK_GT(num_streams, 0); num_streams_ = num_streams; - preconnect_delegate_ = delegate; - return StartInternal(request_info, ssl_config, proxy_info, net_log); -} - -int HttpStreamRequest::RestartWithCertificate(X509Certificate* client_cert) { - ssl_config()->client_cert = client_cert; - ssl_config()->send_client_cert = true; - next_state_ = STATE_INIT_CONNECTION; - // Reset the other member variables. - // Note: this is necessary only with SSL renegotiation. - stream_.reset(); - return RunLoop(OK); + return StartInternal(request_info, ssl_config, net_log); } -int HttpStreamRequest::RestartTunnelWithProxyAuth(const string16& username, - const string16& password) { +int HttpStreamFactoryImpl::Job::RestartTunnelWithProxyAuth( + const string16& username, const string16& password) { DCHECK(establishing_tunnel_); next_state_ = STATE_RESTART_TUNNEL_AUTH; stream_.reset(); return RunLoop(OK); } -LoadState HttpStreamRequest::GetLoadState() const { +LoadState HttpStreamFactoryImpl::Job::GetLoadState() const { switch (next_state_) { case STATE_RESOLVE_PROXY_COMPLETE: return LOAD_STATE_RESOLVING_PROXY_FOR_URL; @@ -148,19 +123,19 @@ LoadState HttpStreamRequest::GetLoadState() const { } } -bool HttpStreamRequest::was_alternate_protocol_available() const { +bool HttpStreamFactoryImpl::Job::was_alternate_protocol_available() const { return was_alternate_protocol_available_; } -bool HttpStreamRequest::was_npn_negotiated() const { +bool HttpStreamFactoryImpl::Job::was_npn_negotiated() const { return was_npn_negotiated_; } -bool HttpStreamRequest::using_spdy() const { +bool HttpStreamFactoryImpl::Job::using_spdy() const { return using_spdy_; } -void HttpStreamRequest::GetSSLInfo() { +void HttpStreamFactoryImpl::Job::GetSSLInfo() { DCHECK(using_ssl_); DCHECK(!establishing_tunnel_); DCHECK(connection_.get() && connection_->socket()); @@ -169,70 +144,59 @@ void HttpStreamRequest::GetSSLInfo() { ssl_socket->GetSSLInfo(&ssl_info_); } -const HttpRequestInfo& HttpStreamRequest::request_info() const { - return *request_info_; -} - -ProxyInfo* HttpStreamRequest::proxy_info() const { - return proxy_info_; -} - -SSLConfig* HttpStreamRequest::ssl_config() const { - return ssl_config_; -} - -void HttpStreamRequest::OnStreamReadyCallback() { +void HttpStreamFactoryImpl::Job::OnStreamReadyCallback() { DCHECK(stream_.get()); - delegate_->OnStreamReady(stream_.release()); + stream_factory_->OnStreamReady( + this, ssl_config_, proxy_info_, stream_.release()); } -void HttpStreamRequest::OnStreamFailedCallback(int result) { - delegate_->OnStreamFailed(result); +void HttpStreamFactoryImpl::Job::OnStreamFailedCallback(int result) { + stream_factory_->OnStreamFailed(this, result, ssl_config_); } -void HttpStreamRequest::OnCertificateErrorCallback(int result, - const SSLInfo& ssl_info) { - delegate_->OnCertificateError(result, ssl_info); +void HttpStreamFactoryImpl::Job::OnCertificateErrorCallback( + int result, const SSLInfo& ssl_info) { + stream_factory_->OnCertificateError(this, result, ssl_config_, ssl_info); } -void HttpStreamRequest::OnNeedsProxyAuthCallback( +void HttpStreamFactoryImpl::Job::OnNeedsProxyAuthCallback( const HttpResponseInfo& response, HttpAuthController* auth_controller) { - delegate_->OnNeedsProxyAuth(response, auth_controller); + stream_factory_->OnNeedsProxyAuth( + this, response, ssl_config_, proxy_info_, auth_controller); } -void HttpStreamRequest::OnNeedsClientAuthCallback( +void HttpStreamFactoryImpl::Job::OnNeedsClientAuthCallback( SSLCertRequestInfo* cert_info) { - delegate_->OnNeedsClientAuth(cert_info); + stream_factory_->OnNeedsClientAuth(this, ssl_config_, cert_info); } -void HttpStreamRequest::OnHttpsProxyTunnelResponseCallback( +void HttpStreamFactoryImpl::Job::OnHttpsProxyTunnelResponseCallback( const HttpResponseInfo& response_info, HttpStream* stream) { - delegate_->OnHttpsProxyTunnelResponse(response_info, stream); + stream_factory_->OnHttpsProxyTunnelResponse( + this, response_info, ssl_config_, proxy_info_, stream); } -void HttpStreamRequest::OnPreconnectsComplete(int result) { - preconnect_delegate_->OnPreconnectsComplete(this, result); +void HttpStreamFactoryImpl::Job::OnPreconnectsComplete() { + stream_factory_->OnPreconnectsComplete(this); } -void HttpStreamRequest::OnIOComplete(int result) { +void HttpStreamFactoryImpl::Job::OnIOComplete(int result) { RunLoop(result); } -int HttpStreamRequest::RunLoop(int result) { +int HttpStreamFactoryImpl::Job::RunLoop(int result) { result = DoLoop(result); - DCHECK(delegate_ || preconnect_delegate_); - if (result == ERR_IO_PENDING) return result; - if (preconnect_delegate_) { + if (IsPreconnecting()) { MessageLoop::current()->PostTask( FROM_HERE, method_factory_.NewRunnableMethod( - &HttpStreamRequest::OnPreconnectsComplete, result)); + &HttpStreamFactoryImpl::Job::OnPreconnectsComplete)); return ERR_IO_PENDING; } @@ -244,7 +208,7 @@ int HttpStreamRequest::RunLoop(int result) { MessageLoop::current()->PostTask( FROM_HERE, method_factory_.NewRunnableMethod( - &HttpStreamRequest::OnCertificateErrorCallback, + &HttpStreamFactoryImpl::Job::OnCertificateErrorCallback, result, ssl_info_)); return ERR_IO_PENDING; } @@ -265,7 +229,7 @@ int HttpStreamRequest::RunLoop(int result) { MessageLoop::current()->PostTask( FROM_HERE, method_factory_.NewRunnableMethod( - &HttpStreamRequest::OnNeedsProxyAuthCallback, + &HttpStreamFactoryImpl::Job::OnNeedsProxyAuthCallback, *tunnel_auth_response, http_proxy_socket->auth_controller())); } @@ -275,7 +239,7 @@ int HttpStreamRequest::RunLoop(int result) { MessageLoop::current()->PostTask( FROM_HERE, method_factory_.NewRunnableMethod( - &HttpStreamRequest::OnNeedsClientAuthCallback, + &HttpStreamFactoryImpl::Job::OnNeedsClientAuthCallback, connection_->ssl_error_response_info().cert_request_info)); return ERR_IO_PENDING; @@ -290,7 +254,7 @@ int HttpStreamRequest::RunLoop(int result) { MessageLoop::current()->PostTask( FROM_HERE, method_factory_.NewRunnableMethod( - &HttpStreamRequest::OnHttpsProxyTunnelResponseCallback, + &HttpStreamFactoryImpl::Job::OnHttpsProxyTunnelResponseCallback, *proxy_socket->GetConnectResponseInfo(), proxy_socket->CreateConnectResponseStream())); return ERR_IO_PENDING; @@ -301,21 +265,21 @@ int HttpStreamRequest::RunLoop(int result) { MessageLoop::current()->PostTask( FROM_HERE, method_factory_.NewRunnableMethod( - &HttpStreamRequest::OnStreamReadyCallback)); + &HttpStreamFactoryImpl::Job::OnStreamReadyCallback)); return ERR_IO_PENDING; default: MessageLoop::current()->PostTask( FROM_HERE, method_factory_.NewRunnableMethod( - &HttpStreamRequest::OnStreamFailedCallback, + &HttpStreamFactoryImpl::Job::OnStreamFailedCallback, result)); return ERR_IO_PENDING; } return result; } -int HttpStreamRequest::DoLoop(int result) { +int HttpStreamFactoryImpl::Job::DoLoop(int result) { DCHECK_NE(next_state_, STATE_NONE); int rv = result; do { @@ -362,14 +326,13 @@ int HttpStreamRequest::DoLoop(int result) { return rv; } -int HttpStreamRequest::StartInternal(const HttpRequestInfo* request_info, - SSLConfig* ssl_config, - ProxyInfo* proxy_info, - const BoundNetLog& net_log) { +int HttpStreamFactoryImpl::Job::StartInternal( + const HttpRequestInfo& request_info, + const SSLConfig& ssl_config, + const BoundNetLog& net_log) { CHECK_EQ(STATE_NONE, next_state_); request_info_ = request_info; ssl_config_ = ssl_config; - proxy_info_ = proxy_info; net_log_ = net_log; next_state_ = STATE_RESOLVE_PROXY; int rv = RunLoop(OK); @@ -377,23 +340,24 @@ int HttpStreamRequest::StartInternal(const HttpRequestInfo* request_info, return rv; } -int HttpStreamRequest::DoResolveProxy() { +int HttpStreamFactoryImpl::Job::DoResolveProxy() { DCHECK(!pac_request_); next_state_ = STATE_RESOLVE_PROXY_COMPLETE; // |endpoint_| indicates the final destination endpoint. - endpoint_ = HostPortPair(request_info().url.HostNoBrackets(), - request_info().url.EffectiveIntPort()); + endpoint_ = HostPortPair(request_info_.url.HostNoBrackets(), + request_info_.url.EffectiveIntPort()); // Extra URL we might be attempting to resolve to. - GURL alternate_endpoint_url = request_info().url; + GURL alternate_endpoint_url = request_info_.url; // Tracks whether we are using |request_.url| or |alternate_endpoint_url|. - const GURL *curr_endpoint_url = &request_info().url; + const GURL *curr_endpoint_url = &request_info_.url; alternate_endpoint_url = - factory_->ApplyHostMappingRules(alternate_endpoint_url, &endpoint_); + HttpStreamFactory::ApplyHostMappingRules( + alternate_endpoint_url, &endpoint_); const HttpAlternateProtocols& alternate_protocols = session_->alternate_protocols(); @@ -416,17 +380,17 @@ int HttpStreamRequest::DoResolveProxy() { } } - if (request_info().load_flags & LOAD_BYPASS_PROXY) { - proxy_info()->UseDirect(); + if (request_info_.load_flags & LOAD_BYPASS_PROXY) { + proxy_info_.UseDirect(); return OK; } return session_->proxy_service()->ResolveProxy( - *curr_endpoint_url, proxy_info(), &io_callback_, &pac_request_, + *curr_endpoint_url, &proxy_info_, &io_callback_, &pac_request_, net_log_); } -int HttpStreamRequest::DoResolveProxyComplete(int result) { +int HttpStreamFactoryImpl::Job::DoResolveProxyComplete(int result) { pac_request_ = NULL; if (result != OK) @@ -436,12 +400,12 @@ int HttpStreamRequest::DoResolveProxyComplete(int result) { // AlternateProtocol. // Remove unsupported proxies from the list. - proxy_info()->RemoveProxiesWithoutScheme( + proxy_info_.RemoveProxiesWithoutScheme( ProxyServer::SCHEME_DIRECT | ProxyServer::SCHEME_HTTP | ProxyServer::SCHEME_HTTPS | ProxyServer::SCHEME_SOCKS4 | ProxyServer::SCHEME_SOCKS5); - if (proxy_info()->is_empty()) { + if (proxy_info_.is_empty()) { // No proxies/direct to choose from. This happens when we don't support any // of the proxies in the returned list. return ERR_NO_SUPPORTED_PROXIES; @@ -451,7 +415,7 @@ int HttpStreamRequest::DoResolveProxyComplete(int result) { return OK; } -bool HasSpdyExclusion(const HostPortPair& endpoint) { +static bool HasSpdyExclusion(const HostPortPair& endpoint) { std::list<HostPortPair>* exclusions = HttpStreamFactory::forced_spdy_exclusions(); if (!exclusions) @@ -464,25 +428,25 @@ bool HasSpdyExclusion(const HostPortPair& endpoint) { return false; } -bool HttpStreamRequest::ShouldForceSpdySSL() { +bool HttpStreamFactoryImpl::Job::ShouldForceSpdySSL() { bool rv = force_spdy_always_ && force_spdy_over_ssl_; return rv && !HasSpdyExclusion(endpoint_); } -bool HttpStreamRequest::ShouldForceSpdyWithoutSSL() { +bool HttpStreamFactoryImpl::Job::ShouldForceSpdyWithoutSSL() { bool rv = force_spdy_always_ && !force_spdy_over_ssl_; return rv && !HasSpdyExclusion(endpoint_); } -int HttpStreamRequest::DoInitConnection() { +int HttpStreamFactoryImpl::Job::DoInitConnection() { DCHECK(!connection_->is_initialized()); - DCHECK(proxy_info()->proxy_server().is_valid()); + DCHECK(proxy_info_.proxy_server().is_valid()); next_state_ = STATE_INIT_CONNECTION_COMPLETE; bool want_spdy_over_npn = alternate_protocol_mode_ == kUsingAlternateProtocol && alternate_protocol_ == HttpAlternateProtocols::NPN_SPDY_2; - using_ssl_ = request_info().url.SchemeIs("https") || + using_ssl_ = request_info_.url.SchemeIs("https") || ShouldForceSpdySSL() || want_spdy_over_npn; using_spdy_ = false; @@ -491,11 +455,11 @@ int HttpStreamRequest::DoInitConnection() { if (HttpStreamFactory::spdy_enabled() && !HasSpdyExclusion(endpoint_)) { // Check first if we have a spdy session for this group. If so, then go // straight to using that. - HostPortProxyPair pair(endpoint_, proxy_info()->proxy_server()); + HostPortProxyPair pair(endpoint_, proxy_info_.proxy_server()); if (session_->spdy_session_pool()->HasSession(pair)) { // If we're preconnecting, but we already have a SpdySession, we don't // actually need to preconnect any sockets, so we're done. - if (preconnect_delegate_) + if (IsPreconnecting()) return OK; using_spdy_ = true; next_state_ = STATE_CREATE_STREAM; @@ -504,7 +468,7 @@ int HttpStreamRequest::DoInitConnection() { // Check next if we have a spdy session for this proxy. If so, then go // straight to using that. if (IsHttpsProxyAndHttpUrl()) { - HostPortProxyPair proxy(proxy_info()->proxy_server().host_port_pair(), + HostPortProxyPair proxy(proxy_info_.proxy_server().host_port_pair(), ProxyServer::Direct()); if (session_->spdy_session_pool()->HasSession(proxy)) { using_spdy_ = true; @@ -524,9 +488,9 @@ int HttpStreamRequest::DoInitConnection() { // If the user is refreshing the page, bypass the host cache. bool disable_resolver_cache = - request_info().load_flags & LOAD_BYPASS_CACHE || - request_info().load_flags & LOAD_VALIDATE_CACHE || - request_info().load_flags & LOAD_DISABLE_CACHE; + request_info_.load_flags & LOAD_BYPASS_CACHE || + request_info_.load_flags & LOAD_VALIDATE_CACHE || + request_info_.load_flags & LOAD_DISABLE_CACHE; // Build up the connection parameters. scoped_refptr<TCPSocketParams> tcp_params; @@ -534,19 +498,19 @@ int HttpStreamRequest::DoInitConnection() { scoped_refptr<SOCKSSocketParams> socks_params; scoped_ptr<HostPortPair> proxy_host_port; - if (proxy_info()->is_direct()) { - tcp_params = new TCPSocketParams(endpoint_, request_info().priority, - request_info().referrer, + if (proxy_info_.is_direct()) { + tcp_params = new TCPSocketParams(endpoint_, request_info_.priority, + request_info_.referrer, disable_resolver_cache); } else { - ProxyServer proxy_server = proxy_info()->proxy_server(); + ProxyServer proxy_server = proxy_info_.proxy_server(); proxy_host_port.reset(new HostPortPair(proxy_server.host_port_pair())); scoped_refptr<TCPSocketParams> proxy_tcp_params( - new TCPSocketParams(*proxy_host_port, request_info().priority, - request_info().referrer, disable_resolver_cache)); + new TCPSocketParams(*proxy_host_port, request_info_.priority, + request_info_.referrer, disable_resolver_cache)); - if (proxy_info()->is_http() || proxy_info()->is_https()) { - GURL authentication_url = request_info().url; + if (proxy_info_.is_http() || proxy_info_.is_https()) { + GURL authentication_url = request_info_.url; if (using_ssl_ && !authentication_url.SchemeIs("https")) { // If a proxy tunnel connection needs to be established due to // an Alternate-Protocol, the URL needs to be changed to indicate @@ -561,10 +525,10 @@ int HttpStreamRequest::DoInitConnection() { } establishing_tunnel_ = using_ssl_; std::string user_agent; - request_info().extra_headers.GetHeader(HttpRequestHeaders::kUserAgent, + request_info_.extra_headers.GetHeader(HttpRequestHeaders::kUserAgent, &user_agent); scoped_refptr<SSLSocketParams> ssl_params; - if (proxy_info()->is_https()) { + if (proxy_info_.is_https()) { // Set ssl_params, and unset proxy_tcp_params ssl_params = GenerateSSLParams(proxy_tcp_params, NULL, NULL, ProxyServer::SCHEME_DIRECT, @@ -579,13 +543,12 @@ int HttpStreamRequest::DoInitConnection() { authentication_url, user_agent, endpoint_, - session_->auth_cache(), + session_->http_auth_cache(), session_->http_auth_handler_factory(), session_->spdy_session_pool(), - session_->mutable_spdy_settings(), using_ssl_); } else { - DCHECK(proxy_info()->is_socks()); + DCHECK(proxy_info_.is_socks()); char socks_version; if (proxy_server.scheme() == ProxyServer::SCHEME_SOCKS5) socks_version = '5'; @@ -597,8 +560,8 @@ int HttpStreamRequest::DoInitConnection() { socks_params = new SOCKSSocketParams(proxy_tcp_params, socks_version == '5', endpoint_, - request_info().priority, - request_info().referrer); + request_info_.priority, + request_info_.referrer); } } @@ -606,71 +569,71 @@ int HttpStreamRequest::DoInitConnection() { if (using_ssl_) { scoped_refptr<SSLSocketParams> ssl_params = GenerateSSLParams(tcp_params, http_proxy_params, socks_params, - proxy_info()->proxy_server().scheme(), - HostPortPair::FromURL(request_info().url), + proxy_info_.proxy_server().scheme(), + HostPortPair::FromURL(request_info_.url), want_spdy_over_npn); SSLClientSocketPool* ssl_pool = NULL; - if (proxy_info()->is_direct()) + if (proxy_info_.is_direct()) ssl_pool = session_->ssl_socket_pool(); else ssl_pool = session_->GetSocketPoolForSSLWithProxy(*proxy_host_port); - if (preconnect_delegate_) { + if (IsPreconnecting()) { RequestSocketsForPool(ssl_pool, connection_group, ssl_params, num_streams_, net_log_); return OK; } return connection_->Init(connection_group, ssl_params, - request_info().priority, &io_callback_, ssl_pool, + request_info_.priority, &io_callback_, ssl_pool, net_log_); } // Finally, get the connection started. - if (proxy_info()->is_http() || proxy_info()->is_https()) { + if (proxy_info_.is_http() || proxy_info_.is_https()) { HttpProxyClientSocketPool* pool = session_->GetSocketPoolForHTTPProxy(*proxy_host_port); - if (preconnect_delegate_) { + if (IsPreconnecting()) { RequestSocketsForPool(pool, connection_group, http_proxy_params, num_streams_, net_log_); return OK; } return connection_->Init(connection_group, http_proxy_params, - request_info().priority, &io_callback_, + request_info_.priority, &io_callback_, pool, net_log_); } - if (proxy_info()->is_socks()) { + if (proxy_info_.is_socks()) { SOCKSClientSocketPool* pool = session_->GetSocketPoolForSOCKSProxy(*proxy_host_port); - if (preconnect_delegate_) { + if (IsPreconnecting()) { RequestSocketsForPool(pool, connection_group, socks_params, num_streams_, net_log_); return OK; } return connection_->Init(connection_group, socks_params, - request_info().priority, &io_callback_, pool, + request_info_.priority, &io_callback_, pool, net_log_); } - DCHECK(proxy_info()->is_direct()); + DCHECK(proxy_info_.is_direct()); TCPClientSocketPool* pool = session_->tcp_socket_pool(); - if (preconnect_delegate_) { + if (IsPreconnecting()) { RequestSocketsForPool(pool, connection_group, tcp_params, num_streams_, net_log_); return OK; } return connection_->Init(connection_group, tcp_params, - request_info().priority, &io_callback_, + request_info_.priority, &io_callback_, pool, net_log_); } -int HttpStreamRequest::DoInitConnectionComplete(int result) { - if (preconnect_delegate_) { +int HttpStreamFactoryImpl::Job::DoInitConnectionComplete(int result) { + if (IsPreconnecting()) { DCHECK_EQ(OK, result); return OK; } @@ -696,7 +659,7 @@ int HttpStreamRequest::DoInitConnectionComplete(int result) { } if (ShouldForceSpdySSL()) SwitchToSpdyMode(); - } else if (proxy_info()->is_https() && connection_->socket() && + } else if (proxy_info_.is_https() && connection_->socket() && result == OK) { HttpProxyClientSocket* proxy_socket = static_cast<HttpProxyClientSocket*>(connection_->socket()); @@ -749,7 +712,7 @@ int HttpStreamRequest::DoInitConnectionComplete(int result) { if (using_ssl_) { DCHECK(ssl_started); if (IsCertificateError(result)) { - if (using_spdy_ && request_info().url.SchemeIs("http")) { + if (using_spdy_ && request_info_.url.SchemeIs("http")) { // We ignore certificate errors for http over spdy. spdy_certificate_error_ = result; result = OK; @@ -771,7 +734,7 @@ int HttpStreamRequest::DoInitConnectionComplete(int result) { return OK; } -int HttpStreamRequest::DoWaitingUserAction(int result) { +int HttpStreamFactoryImpl::Job::DoWaitingUserAction(int result) { // This state indicates that the stream request is in a partially // completed state, and we've called back to the delegate for more // information. @@ -780,7 +743,7 @@ int HttpStreamRequest::DoWaitingUserAction(int result) { return ERR_IO_PENDING; } -int HttpStreamRequest::DoCreateStream() { +int HttpStreamFactoryImpl::Job::DoCreateStream() { next_state_ = STATE_CREATE_STREAM_COMPLETE; // We only set the socket motivation if we're the first to use @@ -789,11 +752,11 @@ int HttpStreamRequest::DoCreateStream() { if (connection_->socket() && !connection_->is_reused()) SetSocketMotivation(); - const ProxyServer& proxy_server = proxy_info()->proxy_server(); + const ProxyServer& proxy_server = proxy_info_.proxy_server(); if (!using_spdy_) { - bool using_proxy = (proxy_info()->is_http() || proxy_info()->is_https()) && - request_info().url.SchemeIs("http"); + bool using_proxy = (proxy_info_.is_http() || proxy_info_.is_https()) && + request_info_.url.SchemeIs("http"); stream_.reset(new HttpBasicStream(connection_.release(), NULL, using_proxy)); return OK; @@ -809,16 +772,14 @@ int HttpStreamRequest::DoCreateStream() { if (spdy_pool->HasSession(pair)) { // We have a SPDY session to the origin server. This might be a direct // connection, or it might be a SPDY session through an HTTP or HTTPS proxy. - spdy_session = - spdy_pool->Get(pair, session_->mutable_spdy_settings(), net_log_); + spdy_session = spdy_pool->Get(pair, net_log_); } else if (IsHttpsProxyAndHttpUrl()) { // If we don't have a direct SPDY session, and we're using an HTTPS // proxy, then we might have a SPDY session to the proxy pair = HostPortProxyPair(proxy_server.host_port_pair(), ProxyServer::Direct()); if (spdy_pool->HasSession(pair)) { - spdy_session = - spdy_pool->Get(pair, session_->mutable_spdy_settings(), net_log_); + spdy_session = spdy_pool->Get(pair, net_log_); } direct = false; } @@ -834,8 +795,8 @@ int HttpStreamRequest::DoCreateStream() { // contain an SSLClientSocket. CHECK(connection_->socket()); int error = spdy_pool->GetSpdySessionFromSocket( - pair, session_->mutable_spdy_settings(), connection_.release(), - net_log_, spdy_certificate_error_, &spdy_session, using_ssl_); + pair, connection_.release(), net_log_, spdy_certificate_error_, + &spdy_session, using_ssl_); if (error != OK) return error; } @@ -843,12 +804,12 @@ int HttpStreamRequest::DoCreateStream() { if (spdy_session->IsClosed()) return ERR_CONNECTION_CLOSED; - bool use_relative_url = direct || request_info().url.SchemeIs("https"); + bool use_relative_url = direct || request_info_.url.SchemeIs("https"); stream_.reset(new SpdyHttpStream(spdy_session, use_relative_url)); return OK; } -int HttpStreamRequest::DoCreateStreamComplete(int result) { +int HttpStreamFactoryImpl::Job::DoCreateStreamComplete(int result) { if (result < 0) return result; @@ -856,14 +817,14 @@ int HttpStreamRequest::DoCreateStreamComplete(int result) { return OK; } -int HttpStreamRequest::DoRestartTunnelAuth() { +int HttpStreamFactoryImpl::Job::DoRestartTunnelAuth() { next_state_ = STATE_RESTART_TUNNEL_AUTH_COMPLETE; HttpProxyClientSocket* http_proxy_socket = static_cast<HttpProxyClientSocket*>(connection_->socket()); return http_proxy_socket->RestartWithAuth(&io_callback_); } -int HttpStreamRequest::DoRestartTunnelAuthComplete(int result) { +int HttpStreamFactoryImpl::Job::DoRestartTunnelAuthComplete(int result) { if (result == ERR_PROXY_AUTH_REQUESTED) return result; @@ -883,21 +844,21 @@ int HttpStreamRequest::DoRestartTunnelAuthComplete(int result) { return ReconsiderProxyAfterError(result); } -void HttpStreamRequest::SetSocketMotivation() { - if (request_info_->motivation == HttpRequestInfo::PRECONNECT_MOTIVATED) +void HttpStreamFactoryImpl::Job::SetSocketMotivation() { + if (request_info_.motivation == HttpRequestInfo::PRECONNECT_MOTIVATED) connection_->socket()->SetSubresourceSpeculation(); - else if (request_info_->motivation == HttpRequestInfo::OMNIBOX_MOTIVATED) + else if (request_info_.motivation == HttpRequestInfo::OMNIBOX_MOTIVATED) connection_->socket()->SetOmniboxSpeculation(); // TODO(mbelshe): Add other motivations (like EARLY_LOAD_MOTIVATED). } -bool HttpStreamRequest::IsHttpsProxyAndHttpUrl() { - return proxy_info()->is_https() && request_info().url.SchemeIs("http"); +bool HttpStreamFactoryImpl::Job::IsHttpsProxyAndHttpUrl() { + return proxy_info_.is_https() && request_info_.url.SchemeIs("http"); } // Returns a newly create SSLSocketParams, and sets several // fields of ssl_config_. -scoped_refptr<SSLSocketParams> HttpStreamRequest::GenerateSSLParams( +scoped_refptr<SSLSocketParams> HttpStreamFactoryImpl::Job::GenerateSSLParams( scoped_refptr<TCPSocketParams> tcp_params, scoped_refptr<HttpProxySocketParams> http_proxy_params, scoped_refptr<SOCKSSocketParams> socks_params, @@ -905,14 +866,14 @@ scoped_refptr<SSLSocketParams> HttpStreamRequest::GenerateSSLParams( const HostPortPair& host_and_port, bool want_spdy_over_npn) { - if (factory_->IsTLSIntolerantServer(request_info().url)) { + if (stream_factory_->IsTLSIntolerantServer(request_info_.url)) { LOG(WARNING) << "Falling back to SSLv3 because host is TLS intolerant: " - << GetHostAndPort(request_info().url); - ssl_config()->ssl3_fallback = true; - ssl_config()->tls1_enabled = false; + << GetHostAndPort(request_info_.url); + ssl_config_.ssl3_fallback = true; + ssl_config_.tls1_enabled = false; } - if (proxy_info()->is_https() && ssl_config()->send_client_cert) { + if (proxy_info_.is_https() && ssl_config_.send_client_cert) { // When connecting through an HTTPS proxy, disable TLS False Start so // that client authentication errors can be distinguished between those // originating from the proxy server (ERR_PROXY_CONNECTION_FAILED) and @@ -921,27 +882,27 @@ scoped_refptr<SSLSocketParams> HttpStreamRequest::GenerateSSLParams( // TODO(rch): This assumes that the HTTPS proxy will only request a // client certificate during the initial handshake. // http://crbug.com/59292 - ssl_config()->false_start_enabled = false; + ssl_config_.false_start_enabled = false; } UMA_HISTOGRAM_ENUMERATION("Net.ConnectionUsedSSLv3Fallback", - static_cast<int>(ssl_config()->ssl3_fallback), 2); + static_cast<int>(ssl_config_.ssl3_fallback), 2); - int load_flags = request_info().load_flags; + int load_flags = request_info_.load_flags; if (HttpStreamFactory::ignore_certificate_errors()) load_flags |= LOAD_IGNORE_ALL_CERT_ERRORS; - if (request_info().load_flags & LOAD_VERIFY_EV_CERT) - ssl_config()->verify_ev_cert = true; + if (request_info_.load_flags & LOAD_VERIFY_EV_CERT) + ssl_config_.verify_ev_cert = true; - if (proxy_info()->proxy_server().scheme() == ProxyServer::SCHEME_HTTP || - proxy_info()->proxy_server().scheme() == ProxyServer::SCHEME_HTTPS) { - ssl_config()->mitm_proxies_allowed = true; + if (proxy_info_.proxy_server().scheme() == ProxyServer::SCHEME_HTTP || + proxy_info_.proxy_server().scheme() == ProxyServer::SCHEME_HTTPS) { + ssl_config_.mitm_proxies_allowed = true; } scoped_refptr<SSLSocketParams> ssl_params( new SSLSocketParams(tcp_params, socks_params, http_proxy_params, proxy_scheme, host_and_port, - *ssl_config(), load_flags, + ssl_config_, load_flags, ShouldForceSpdySSL(), want_spdy_over_npn)); @@ -949,7 +910,7 @@ scoped_refptr<SSLSocketParams> HttpStreamRequest::GenerateSSLParams( } -void HttpStreamRequest::MarkBrokenAlternateProtocolAndFallback() { +void HttpStreamFactoryImpl::Job::MarkBrokenAlternateProtocolAndFallback() { // We have to: // * Reset the endpoint to be the unmodified URL specified destination. // * Mark the endpoint as broken so we don't try again. @@ -957,8 +918,8 @@ void HttpStreamRequest::MarkBrokenAlternateProtocolAndFallback() { // ignore future Alternate-Protocol headers from the HostPortPair. // * Reset the connection and go back to STATE_INIT_CONNECTION. - endpoint_ = HostPortPair(request_info().url.HostNoBrackets(), - request_info().url.EffectiveIntPort()); + endpoint_ = HostPortPair(request_info_.url.HostNoBrackets(), + request_info_.url.EffectiveIntPort()); session_->mutable_alternate_protocols()->MarkBrokenAlternateProtocolFor( endpoint_); @@ -970,7 +931,7 @@ void HttpStreamRequest::MarkBrokenAlternateProtocolAndFallback() { next_state_ = STATE_INIT_CONNECTION; } -int HttpStreamRequest::ReconsiderProxyAfterError(int error) { +int HttpStreamFactoryImpl::Job::ReconsiderProxyAfterError(int error) { DCHECK(!pac_request_); // A failure to resolve the hostname or any error related to establishing a @@ -1008,17 +969,17 @@ int HttpStreamRequest::ReconsiderProxyAfterError(int error) { return error; } - if (request_info().load_flags & LOAD_BYPASS_PROXY) { + if (request_info_.load_flags & LOAD_BYPASS_PROXY) { return error; } - if (proxy_info()->is_https() && ssl_config()->send_client_cert) { + if (proxy_info_.is_https() && ssl_config_.send_client_cert) { session_->ssl_client_auth_cache()->Remove( - proxy_info()->proxy_server().host_port_pair().ToString()); + proxy_info_.proxy_server().host_port_pair().ToString()); } int rv = session_->proxy_service()->ReconsiderProxyAfterError( - request_info().url, proxy_info(), &io_callback_, &pac_request_, + request_info_.url, &proxy_info_, &io_callback_, &pac_request_, net_log_); if (rv == OK || rv == ERR_IO_PENDING) { // If the error was during connection setup, there is no socket to @@ -1038,7 +999,7 @@ int HttpStreamRequest::ReconsiderProxyAfterError(int error) { return rv; } -int HttpStreamRequest::HandleCertificateError(int error) { +int HttpStreamFactoryImpl::Job::HandleCertificateError(int error) { DCHECK(using_ssl_); DCHECK(IsCertificateError(error)); @@ -1053,9 +1014,9 @@ int HttpStreamRequest::HandleCertificateError(int error) { SSLConfig::CertAndStatus bad_cert; bad_cert.cert = ssl_info_.cert; bad_cert.cert_status = ssl_info_.cert_status; - ssl_config()->allowed_bad_certs.push_back(bad_cert); + ssl_config_.allowed_bad_certs.push_back(bad_cert); - int load_flags = request_info().load_flags; + int load_flags = request_info_.load_flags; if (HttpStreamFactory::ignore_certificate_errors()) load_flags |= LOAD_IGNORE_ALL_CERT_ERRORS; if (ssl_socket->IgnoreCertError(error, load_flags)) @@ -1063,13 +1024,13 @@ int HttpStreamRequest::HandleCertificateError(int error) { return error; } -void HttpStreamRequest::SwitchToSpdyMode() { +void HttpStreamFactoryImpl::Job::SwitchToSpdyMode() { if (HttpStreamFactory::spdy_enabled()) using_spdy_ = true; } // static -void HttpStreamRequest::LogHttpConnectedMetrics( +void HttpStreamFactoryImpl::Job::LogHttpConnectedMetrics( const ClientSocketHandle& handle) { UMA_HISTOGRAM_ENUMERATION("Net.HttpSocketType", handle.reuse_type(), ClientSocketHandle::NUM_TYPES); @@ -1102,4 +1063,9 @@ void HttpStreamRequest::LogHttpConnectedMetrics( } } +bool HttpStreamFactoryImpl::Job::IsPreconnecting() const { + DCHECK_GE(num_streams_, 0); + return num_streams_ > 0; +} + } // namespace net diff --git a/net/http/http_stream_request.h b/net/http/http_stream_factory_impl_job.h index fca2332..38f8081 100644 --- a/net/http/http_stream_request.h +++ b/net/http/http_stream_factory_impl_job.h @@ -1,19 +1,20 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef NET_HTTP_HTTP_STREAM_REQUEST_H_ -#define NET_HTTP_HTTP_STREAM_REQUEST_H_ +#ifndef NET_HTTP_HTTP_STREAM_FACTORY_IMPL_JOB_H_ +#define NET_HTTP_HTTP_STREAM_FACTORY_IMPL_JOB_H_ +#include "base/ref_counted.h" #include "base/scoped_ptr.h" #include "base/task.h" #include "net/base/completion_callback.h" -#include "net/base/host_mapping_rules.h" #include "net/base/ssl_config_service.h" +#include "net/http/http_alternate_protocols.h" #include "net/http/http_auth.h" #include "net/http/http_auth_controller.h" -#include "net/http/http_alternate_protocols.h" -#include "net/http/stream_factory.h" +#include "net/http/http_request_info.h" +#include "net/http/http_stream_factory_impl.h" #include "net/proxy/proxy_service.h" #include "net/socket/client_socket_handle.h" @@ -23,55 +24,39 @@ class ClientSocketHandle; class HttpAuthController; class HttpNetworkSession; class HttpProxySocketParams; +class HttpStream; class SOCKSSocketParams; class SSLSocketParams; -class StreamRequestDelegate; class TCPSocketParams; -struct HttpRequestInfo; -// An HttpStreamRequest exists for each stream which is in progress of being +// An HttpStreamRequestImpl exists for each stream which is in progress of being // created for the StreamFactory. -class HttpStreamRequest : public StreamRequest { +class HttpStreamFactoryImpl::Job { public: - class PreconnectDelegate { - public: - virtual ~PreconnectDelegate() {} - - virtual void OnPreconnectsComplete(HttpStreamRequest* request, - int result) = 0; - }; - - HttpStreamRequest(StreamFactory* factory, - HttpNetworkSession* session); - virtual ~HttpStreamRequest(); + Job(HttpStreamFactoryImpl* stream_factory, HttpNetworkSession* session); + ~Job(); // Start initiates the process of creating a new HttpStream. // 3 parameters are passed in by reference. The caller asserts that the // lifecycle of these parameters will remain valid until the stream is // created, failed, or destroyed. In the first two cases, the delegate will // be called to notify completion of the request. - void Start(const HttpRequestInfo* request_info, - SSLConfig* ssl_config, - ProxyInfo* proxy_info, - Delegate* delegate, + void Start(const HttpRequestInfo& request_info, + const SSLConfig& ssl_config, const BoundNetLog& net_log); int Preconnect(int num_streams, - const HttpRequestInfo* request_info, - SSLConfig* ssl_config, - ProxyInfo* proxy_info, - PreconnectDelegate* delegate, + const HttpRequestInfo& request_info, + const SSLConfig& ssl_config, const BoundNetLog& net_log); - // StreamRequest interface - virtual int RestartWithCertificate(X509Certificate* client_cert); - virtual int RestartTunnelWithProxyAuth(const string16& username, - const string16& password); - virtual LoadState GetLoadState() const; + int RestartTunnelWithProxyAuth(const string16& username, + const string16& password); + LoadState GetLoadState() const; - virtual bool was_alternate_protocol_available() const; - virtual bool was_npn_negotiated() const; - virtual bool using_spdy() const; + bool was_alternate_protocol_available() const; + bool was_npn_negotiated() const; + bool using_spdy() const; private: enum AlternateProtocolMode { @@ -96,11 +81,6 @@ class HttpStreamRequest : public StreamRequest { STATE_NONE }; - const HttpRequestInfo& request_info() const; - ProxyInfo* proxy_info() const; - SSLConfig* ssl_config() const; - - // Callbacks to the delegate. void OnStreamReadyCallback(); void OnStreamFailedCallback(int result); void OnCertificateErrorCallback(int result, const SSLInfo& ssl_info); @@ -109,14 +89,13 @@ class HttpStreamRequest : public StreamRequest { void OnNeedsClientAuthCallback(SSLCertRequestInfo* cert_info); void OnHttpsProxyTunnelResponseCallback(const HttpResponseInfo& response_info, HttpStream* stream); - void OnPreconnectsComplete(int result); + void OnPreconnectsComplete(); void OnIOComplete(int result); int RunLoop(int result); int DoLoop(int result); - int StartInternal(const HttpRequestInfo* request_info, - SSLConfig* ssl_config, - ProxyInfo* proxy_info, + int StartInternal(const HttpRequestInfo& request_info, + const SSLConfig& ssl_config, const BoundNetLog& net_log); // Each of these methods corresponds to a State value. Those with an input @@ -184,15 +163,17 @@ class HttpStreamRequest : public StreamRequest { // Record histograms of latency until Connect() completes. static void LogHttpConnectedMetrics(const ClientSocketHandle& handle); - const HttpRequestInfo* request_info_; // Use request_info(). - ProxyInfo* proxy_info_; // Use proxy_info(). - SSLConfig* ssl_config_; // Use ssl_config(). + // Indicates whether or not this job is performing a preconnect. + bool IsPreconnecting() const; - scoped_refptr<HttpNetworkSession> session_; - CompletionCallbackImpl<HttpStreamRequest> io_callback_; + HttpRequestInfo request_info_; + ProxyInfo proxy_info_; + SSLConfig ssl_config_; + + CompletionCallbackImpl<Job> io_callback_; scoped_ptr<ClientSocketHandle> connection_; - StreamFactory* const factory_; - Delegate* delegate_; + HttpNetworkSession* const session_; + HttpStreamFactoryImpl* const stream_factory_; BoundNetLog net_log_; State next_state_; ProxyService::PacRequest* pac_request_; @@ -217,7 +198,7 @@ class HttpStreamRequest : public StreamRequest { int spdy_certificate_error_; scoped_refptr<HttpAuthController> - auth_controllers_[HttpAuth::AUTH_NUM_TARGETS]; + auth_controllers_[HttpAuth::AUTH_NUM_TARGETS]; AlternateProtocolMode alternate_protocol_mode_; @@ -237,16 +218,15 @@ class HttpStreamRequest : public StreamRequest { // True if we negotiated NPN. bool was_npn_negotiated_; - PreconnectDelegate* preconnect_delegate_; - - // Only used if |preconnect_delegate_| is non-NULL. + // 0 if we're not preconnecting. Otherwise, the number of streams to + // preconnect. int num_streams_; - ScopedRunnableMethodFactory<HttpStreamRequest> method_factory_; + ScopedRunnableMethodFactory<Job> method_factory_; - DISALLOW_COPY_AND_ASSIGN(HttpStreamRequest); + DISALLOW_COPY_AND_ASSIGN(Job); }; } // namespace net -#endif // NET_HTTP_HTTP_STREAM_REQUEST_H_ +#endif // NET_HTTP_HTTP_STREAM_FACTORY_IMPL_JOB_H_ diff --git a/net/http/http_stream_factory_unittest.cc b/net/http/http_stream_factory_impl_unittest.cc index 617d885..f316251 100644 --- a/net/http/http_stream_factory_unittest.cc +++ b/net/http/http_stream_factory_impl_unittest.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "net/http/http_stream_factory.h" +#include "net/http/http_stream_factory_impl.h" #include <string> @@ -16,6 +16,8 @@ #include "net/http/http_network_session.h" #include "net/http/http_network_session_peer.h" #include "net/http/http_request_info.h" +#include "net/proxy/proxy_info.h" +#include "net/proxy/proxy_service.h" #include "net/socket/socket_test_util.h" #include "net/spdy/spdy_session.h" #include "net/spdy/spdy_session_pool.h" @@ -25,6 +27,34 @@ namespace net { namespace { +class MockHttpStreamFactoryImpl : public HttpStreamFactoryImpl { + public: + MockHttpStreamFactoryImpl(HttpNetworkSession* session) + : HttpStreamFactoryImpl(session), + preconnect_done_(false), + waiting_for_preconnect_(false) {} + + + void WaitForPreconnects() { + while (!preconnect_done_) { + waiting_for_preconnect_ = true; + MessageLoop::current()->Run(); + waiting_for_preconnect_ = false; + } + } + + private: + // HttpStreamFactoryImpl methods. + virtual void OnPreconnectsCompleteInternal() { + preconnect_done_ = true; + if (waiting_for_preconnect_) + MessageLoop::current()->Quit(); + } + + bool preconnect_done_; + bool waiting_for_preconnect_; +}; + struct SessionDependencies { // Custom proxy service dependency. explicit SessionDependencies(ProxyService* proxy_service) @@ -70,8 +100,12 @@ TestCase kTests[] = { { 2, true}, }; -int PreconnectHelper(const TestCase& test, - HttpNetworkSession* session) { +void PreconnectHelper(const TestCase& test, + HttpNetworkSession* session) { + HttpNetworkSessionPeer peer(session); + MockHttpStreamFactoryImpl* mock_factory = + new MockHttpStreamFactoryImpl(session); + peer.SetHttpStreamFactory(mock_factory); SSLConfig ssl_config; session->ssl_config_service()->GetSSLConfig(&ssl_config); @@ -84,12 +118,9 @@ int PreconnectHelper(const TestCase& test, ProxyInfo proxy_info; TestCompletionCallback callback; - int rv = session->http_stream_factory()->PreconnectStreams( - test.num_streams, &request, &ssl_config, &proxy_info, session, - BoundNetLog(), &callback); - if (rv != ERR_IO_PENDING) - return ERR_UNEXPECTED; - return callback.WaitForResult(); + session->http_stream_factory()->PreconnectStreams( + test.num_streams, request, ssl_config, BoundNetLog()); + mock_factory->WaitForPreconnects(); }; template<typename ParentPool> @@ -195,7 +226,7 @@ TEST(HttpStreamFactoryTest, PreconnectDirect) { session_deps.host_resolver.get(), session_deps.cert_verifier.get()); peer.SetSSLSocketPool(ssl_conn_pool); - EXPECT_EQ(OK, PreconnectHelper(kTests[i], session)); + PreconnectHelper(kTests[i], session); if (kTests[i].ssl) EXPECT_EQ(kTests[i].num_streams, ssl_conn_pool->last_num_streams()); else @@ -219,7 +250,7 @@ TEST(HttpStreamFactoryTest, PreconnectHttpProxy) { session_deps.host_resolver.get(), session_deps.cert_verifier.get()); peer.SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool); - EXPECT_EQ(OK, PreconnectHelper(kTests[i], session)); + PreconnectHelper(kTests[i], session); if (kTests[i].ssl) EXPECT_EQ(kTests[i].num_streams, ssl_conn_pool->last_num_streams()); else @@ -244,7 +275,7 @@ TEST(HttpStreamFactoryTest, PreconnectSocksProxy) { session_deps.host_resolver.get(), session_deps.cert_verifier.get()); peer.SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool); - EXPECT_EQ(OK, PreconnectHelper(kTests[i], session)); + PreconnectHelper(kTests[i], session); if (kTests[i].ssl) EXPECT_EQ(kTests[i].num_streams, ssl_conn_pool->last_num_streams()); else @@ -262,8 +293,7 @@ TEST(HttpStreamFactoryTest, PreconnectDirectWithExistingSpdySession) { HostPortPair host_port_pair("www.google.com", 443); HostPortProxyPair pair(host_port_pair, ProxyServer::Direct()); scoped_refptr<SpdySession> spdy_session = - session->spdy_session_pool()->Get( - pair, session->mutable_spdy_settings(), BoundNetLog()); + session->spdy_session_pool()->Get(pair, BoundNetLog()); CapturePreconnectsTCPSocketPool* tcp_conn_pool = new CapturePreconnectsTCPSocketPool( @@ -275,7 +305,7 @@ TEST(HttpStreamFactoryTest, PreconnectDirectWithExistingSpdySession) { session_deps.host_resolver.get(), session_deps.cert_verifier.get()); peer.SetSSLSocketPool(ssl_conn_pool); - EXPECT_EQ(OK, PreconnectHelper(kTests[i], session)); + PreconnectHelper(kTests[i], session); // We shouldn't be preconnecting if we have an existing session, which is // the case for https://www.google.com. if (kTests[i].ssl) diff --git a/net/http/stream_factory.h b/net/http/stream_factory.h deleted file mode 100644 index 1a7aa77..0000000 --- a/net/http/stream_factory.h +++ /dev/null @@ -1,156 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef NET_HTTP_STREAM_FACTORY_H_ -#define NET_HTTP_STREAM_FACTORY_H_ - -#include <string> - -#include "base/ref_counted.h" -#include "net/base/completion_callback.h" -#include "net/base/load_states.h" - -namespace net { - -class BoundNetLog; -class HostPortPair; -class HttpAlternateProtocols; -class HttpAuthController; -class HttpNetworkSession; -class HttpResponseInfo; -class HttpStream; -class ProxyInfo; -class SSLCertRequestInfo; -class SSLInfo; -class X509Certificate; -struct HttpRequestInfo; -struct SSLConfig; - -// The StreamRequest is the client's handle to the worker object which handles -// the creation of an HttpStream. While the HttpStream is being created, this -// object is the creator's handle for interacting with the HttpStream creation -// process. The request is cancelled by deleting it, after which no callbacks -// will be invoked. -class StreamRequest { - public: - // The StreamRequestDelegate is a set of callback methods for a - // StreamRequestJob. Generally, only one of these methods will be - // called as a result of a stream request. - class Delegate { - public: - virtual ~Delegate() {} - - // This is the success case. - // |stream| is now owned by the delegate. - virtual void OnStreamReady(HttpStream* stream) = 0; - - // This is the failure to create a stream case. - virtual void OnStreamFailed(int status) = 0; - - // Called when we have a certificate error for the request. - virtual void OnCertificateError(int status, const SSLInfo& ssl_info) = 0; - - // This is the failure case where we need proxy authentication during - // proxy tunnel establishment. For the tunnel case, we were unable to - // create the HttpStream, so the caller provides the auth and then resumes - // the StreamRequest. For the non-tunnel case, the caller will handle - // the authentication failure and restart the StreamRequest entirely. - // Ownership of |auth_controller| and |proxy_response| are owned - // by the StreamRequest. |proxy_response| is not guaranteed to be usable - // after the lifetime of this callback. The delegate may take a reference - // to |auth_controller| if it is needed beyond the lifetime of this - // callback. - virtual void OnNeedsProxyAuth(const HttpResponseInfo& proxy_response, - HttpAuthController* auth_controller) = 0; - - // This is the failure for SSL Client Auth - // Ownership of |cert_info| is retained by the StreamRequest. The delegate - // may take a reference if it needs the cert_info beyond the lifetime of - // this callback. - virtual void OnNeedsClientAuth(SSLCertRequestInfo* cert_info) = 0; - - // This is the failure of the CONNECT request through an HTTPS proxy. - // Headers can be read from |response_info|, while the body can be read - // from |stream|. - // Ownership of |stream| is transferred to the delegate. - virtual void OnHttpsProxyTunnelResponse( - const HttpResponseInfo& response_info, HttpStream* stream) = 0; - }; - - virtual ~StreamRequest() {} - - // When a HttpStream creation process requires a SSL Certificate, - // the delegate OnNeedsClientAuth handler will have been called. - // It now becomes the delegate's responsibility to collect the certificate - // (probably from the user), and then call this method to resume - // the HttpStream creation process. - // Ownership of |client_cert| remains with the StreamRequest. The - // delegate can take a reference if needed beyond the lifetime of this - // call. - virtual int RestartWithCertificate(X509Certificate* client_cert) = 0; - - // When a HttpStream creation process is stalled due to necessity - // of Proxy authentication credentials, the delegate OnNeedsProxyAuth - // will have been called. It now becomes the delegate's responsibility - // to collect the necessary credentials, and then call this method to - // resume the HttpStream creation process. - virtual int RestartTunnelWithProxyAuth(const string16& username, - const string16& password) = 0; - - // Returns the LoadState for the request. - virtual LoadState GetLoadState() const = 0; - - // Returns true if an AlternateProtocol for this request was available. - virtual bool was_alternate_protocol_available() const = 0; - - // Returns true if TLS/NPN was negotiated for this stream. - virtual bool was_npn_negotiated() const = 0; - - // Returns true if this stream is being fetched over SPDY. - virtual bool using_spdy() const = 0; -}; - -// The StreamFactory defines an interface for creating usable HttpStreams. -class StreamFactory { - public: - virtual ~StreamFactory() {} - - // Request a stream. - // Will callback to the StreamRequestDelegate upon completion. - // |info|, |ssl_config|, and |proxy_info| must be kept alive until - // |delegate| is called. - virtual StreamRequest* RequestStream(const HttpRequestInfo* info, - SSLConfig* ssl_config, - ProxyInfo* proxy_info, - HttpNetworkSession* session, - StreamRequest::Delegate* delegate, - const BoundNetLog& net_log) = 0; - - // Requests that enough connections for |num_streams| be opened. If - // ERR_IO_PENDING is returned, |info|, |ssl_config|, and |proxy_info| must - // be kept alive until |callback| is invoked. That callback will be given the - // final error code. - virtual int PreconnectStreams(int num_streams, - const HttpRequestInfo* info, - SSLConfig* ssl_config, - ProxyInfo* proxy_info, - HttpNetworkSession* session, - const BoundNetLog& net_log, - CompletionCallback* callback) = 0; - - virtual void AddTLSIntolerantServer(const GURL& url) = 0; - virtual bool IsTLSIntolerantServer(const GURL& url) = 0; - - virtual void ProcessAlternateProtocol( - HttpAlternateProtocols* alternate_protocols, - const std::string& alternate_protocol_str, - const HostPortPair& http_host_port_pair) = 0; - - virtual GURL ApplyHostMappingRules(const GURL& url, - HostPortPair* endpoint) = 0; -}; - -} // namespace net - -#endif // NET_HTTP_STREAM_FACTORY_H_ diff --git a/net/net.gyp b/net/net.gyp index 5266f74a..3cfd242 100644 --- a/net/net.gyp +++ b/net/net.gyp @@ -505,10 +505,12 @@ 'http/http_stream.h', 'http/http_stream_factory.cc', 'http/http_stream_factory.h', + 'http/http_stream_factory_impl.cc', + 'http/http_stream_factory_impl.h', + 'http/http_stream_factory_impl_job.cc', + 'http/http_stream_factory_impl_job.h', 'http/http_stream_parser.cc', 'http/http_stream_parser.h', - 'http/http_stream_request.cc', - 'http/http_stream_request.h', 'http/http_transaction.h', 'http/http_transaction_factory.h', 'http/url_security_manager.h', @@ -532,7 +534,6 @@ 'http/partial_data.cc', 'http/partial_data.h', 'http/proxy_client_socket.h', - 'http/stream_factory.h', 'ocsp/nss_ocsp.cc', 'ocsp/nss_ocsp.h', 'proxy/init_proxy_resolver.cc', @@ -943,7 +944,7 @@ 'http/http_request_headers_unittest.cc', 'http/http_response_body_drainer_unittest.cc', 'http/http_response_headers_unittest.cc', - 'http/http_stream_factory_unittest.cc', + 'http/http_stream_factory_impl_unittest.cc', 'http/http_transaction_unittest.cc', 'http/http_transaction_unittest.h', 'http/http_util_unittest.cc', diff --git a/net/socket/client_socket_pool_manager.cc b/net/socket/client_socket_pool_manager.cc index 8516fbc..999b4e6 100644 --- a/net/socket/client_socket_pool_manager.cc +++ b/net/socket/client_socket_pool_manager.cc @@ -152,6 +152,55 @@ void ClientSocketPoolManager::FlushSocketPools() { tcp_socket_pool_->Flush(); } +void ClientSocketPoolManager::CloseIdleSockets() { + // Close sockets in the highest level pools first, since higher level pools' + // sockets may release stuff to the lower level pools. + for (SSLSocketPoolMap::const_iterator it = + ssl_socket_pools_for_proxies_.begin(); + it != ssl_socket_pools_for_proxies_.end(); + ++it) + it->second->CloseIdleSockets(); + + for (HTTPProxySocketPoolMap::const_iterator it = + http_proxy_socket_pools_.begin(); + it != http_proxy_socket_pools_.end(); + ++it) + it->second->CloseIdleSockets(); + + for (SSLSocketPoolMap::const_iterator it = + ssl_socket_pools_for_https_proxies_.begin(); + it != ssl_socket_pools_for_https_proxies_.end(); + ++it) + it->second->CloseIdleSockets(); + + for (TCPSocketPoolMap::const_iterator it = + tcp_socket_pools_for_https_proxies_.begin(); + it != tcp_socket_pools_for_https_proxies_.end(); + ++it) + it->second->CloseIdleSockets(); + + for (TCPSocketPoolMap::const_iterator it = + tcp_socket_pools_for_http_proxies_.begin(); + it != tcp_socket_pools_for_http_proxies_.end(); + ++it) + it->second->CloseIdleSockets(); + + for (SOCKSSocketPoolMap::const_iterator it = + socks_socket_pools_.begin(); + it != socks_socket_pools_.end(); + ++it) + it->second->CloseIdleSockets(); + + for (TCPSocketPoolMap::const_iterator it = + tcp_socket_pools_for_socks_proxies_.begin(); + it != tcp_socket_pools_for_socks_proxies_.end(); + ++it) + it->second->CloseIdleSockets(); + + ssl_socket_pool_->CloseIdleSockets(); + tcp_socket_pool_->CloseIdleSockets(); +} + SOCKSClientSocketPool* ClientSocketPoolManager::GetSocketPoolForSOCKSProxy( const HostPortPair& socks_proxy) { SOCKSSocketPoolMap::const_iterator it = socks_socket_pools_.find(socks_proxy); diff --git a/net/socket/client_socket_pool_manager.h b/net/socket/client_socket_pool_manager.h index d6d09e91..7d610a9 100644 --- a/net/socket/client_socket_pool_manager.h +++ b/net/socket/client_socket_pool_manager.h @@ -71,6 +71,7 @@ class ClientSocketPoolManager : public base::NonThreadSafe { ~ClientSocketPoolManager(); void FlushSocketPools(); + void CloseIdleSockets(); TCPClientSocketPool* tcp_socket_pool() { return tcp_socket_pool_.get(); } diff --git a/net/socket/ssl_client_socket_pool_unittest.cc b/net/socket/ssl_client_socket_pool_unittest.cc index e211591..091a94ae 100644 --- a/net/socket/ssl_client_socket_pool_unittest.cc +++ b/net/socket/ssl_client_socket_pool_unittest.cc @@ -19,6 +19,7 @@ #include "net/http/http_network_session.h" #include "net/http/http_request_headers.h" #include "net/http/http_response_headers.h" +#include "net/proxy/proxy_service.h" #include "net/socket/client_socket_handle.h" #include "net/socket/client_socket_pool_histograms.h" #include "net/socket/socket_test_util.h" @@ -62,10 +63,9 @@ class SSLClientSocketPoolTest : public testing::Test { http_proxy_socket_params_(new HttpProxySocketParams( proxy_tcp_socket_params_, NULL, GURL("http://host"), "", HostPortPair("host", 80), - session_->auth_cache(), + session_->http_auth_cache(), session_->http_auth_handler_factory(), session_->spdy_session_pool(), - session_->mutable_spdy_settings(), true)), http_proxy_histograms_("MockHttpProxy"), http_proxy_socket_pool_( @@ -117,13 +117,13 @@ class SSLClientSocketPoolTest : public testing::Test { void AddAuthToCache() { const string16 kFoo(ASCIIToUTF16("foo")); const string16 kBar(ASCIIToUTF16("bar")); - session_->auth_cache()->Add(GURL("http://proxy:443/"), - "MyRealm1", - HttpAuth::AUTH_SCHEME_BASIC, - "Basic realm=MyRealm1", - kFoo, - kBar, - "/"); + session_->http_auth_cache()->Add(GURL("http://proxy:443/"), + "MyRealm1", + HttpAuth::AUTH_SCHEME_BASIC, + "Basic realm=MyRealm1", + kFoo, + kBar, + "/"); } HttpNetworkSession* CreateNetworkSession() { diff --git a/net/spdy/spdy_http_stream_unittest.cc b/net/spdy/spdy_http_stream_unittest.cc index df979ec..1688871 100644 --- a/net/spdy/spdy_http_stream_unittest.cc +++ b/net/spdy/spdy_http_stream_unittest.cc @@ -29,8 +29,7 @@ class SpdyHttpStreamTest : public testing::Test { data_ = new OrderedSocketData(reads, reads_count, writes, writes_count); session_deps_.socket_factory->AddSocketDataProvider(data_.get()); http_session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps_); - session_ = http_session_->spdy_session_pool()-> - Get(pair, http_session_->mutable_spdy_settings(), BoundNetLog()); + session_ = http_session_->spdy_session_pool()->Get(pair, BoundNetLog()); tcp_params_ = new TCPSocketParams(host_port_pair.host(), host_port_pair.port(), MEDIUM, GURL(), false); diff --git a/net/spdy/spdy_network_transaction_unittest.cc b/net/spdy/spdy_network_transaction_unittest.cc index 402f2f7..019cc4c 100644 --- a/net/spdy/spdy_network_transaction_unittest.cc +++ b/net/spdy/spdy_network_transaction_unittest.cc @@ -393,8 +393,7 @@ class SpdyNetworkTransactionTest const scoped_refptr<HttpNetworkSession>& session = helper.session(); SpdySessionPool* pool(session->spdy_session_pool()); EXPECT_TRUE(pool->HasSession(pair)); - scoped_refptr<SpdySession> spdy_session( - pool->Get(pair, session->mutable_spdy_settings(), log)); + scoped_refptr<SpdySession> spdy_session(pool->Get(pair, log)); ASSERT_TRUE(spdy_session.get() != NULL); EXPECT_EQ(0u, spdy_session->num_active_streams()); EXPECT_EQ(0u, spdy_session->num_unclaimed_pushed_streams()); @@ -4016,7 +4015,8 @@ TEST_P(SpdyNetworkTransactionTest, SettingsSaved) { // Verify that no settings exist initially. HostPortPair host_port_pair("www.google.com", helper.port()); - EXPECT_TRUE(helper.session()->spdy_settings().Get(host_port_pair).empty()); + SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool(); + EXPECT_TRUE(spdy_session_pool->spdy_settings().Get(host_port_pair).empty()); // Construct the request. scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST)); @@ -4078,7 +4078,7 @@ TEST_P(SpdyNetworkTransactionTest, SettingsSaved) { { // Verify we had two persisted settings. spdy::SpdySettings saved_settings = - helper.session()->spdy_settings().Get(host_port_pair); + spdy_session_pool->spdy_settings().Get(host_port_pair); ASSERT_EQ(2u, saved_settings.size()); // Verify the first persisted setting. @@ -4124,7 +4124,8 @@ TEST_P(SpdyNetworkTransactionTest, SettingsPlayback) { // Verify that no settings exist initially. HostPortPair host_port_pair("www.google.com", helper.port()); - EXPECT_TRUE(helper.session()->spdy_settings().Get(host_port_pair).empty()); + SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool(); + EXPECT_TRUE(spdy_session_pool->spdy_settings().Get(host_port_pair).empty()); unsigned int kSampleId1 = 0x1; unsigned int kSampleValue1 = 0x0a0a0a0a; @@ -4143,14 +4144,14 @@ TEST_P(SpdyNetworkTransactionTest, SettingsPlayback) { setting.set_id(kSampleId2); settings.push_back(std::make_pair(setting, kSampleValue2)); - helper.session()->mutable_spdy_settings()->Set(host_port_pair, settings); + spdy_session_pool->mutable_spdy_settings()->Set(host_port_pair, settings); } - EXPECT_EQ(2u, helper.session()->spdy_settings().Get(host_port_pair).size()); + EXPECT_EQ(2u, spdy_session_pool->spdy_settings().Get(host_port_pair).size()); // Construct the SETTINGS frame. const spdy::SpdySettings& settings = - helper.session()->spdy_settings().Get(host_port_pair); + spdy_session_pool->spdy_settings().Get(host_port_pair); scoped_ptr<spdy::SpdyFrame> settings_frame(ConstructSpdySettings(settings)); // Construct the request. @@ -4190,7 +4191,7 @@ TEST_P(SpdyNetworkTransactionTest, SettingsPlayback) { { // Verify we had two persisted settings. spdy::SpdySettings saved_settings = - helper.session()->spdy_settings().Get(host_port_pair); + spdy_session_pool->spdy_settings().Get(host_port_pair); ASSERT_EQ(2u, saved_settings.size()); // Verify the first persisted setting. diff --git a/net/spdy/spdy_proxy_client_socket_unittest.cc b/net/spdy/spdy_proxy_client_socket_unittest.cc index e4483bd..9023ca9 100644 --- a/net/spdy/spdy_proxy_client_socket_unittest.cc +++ b/net/spdy/spdy_proxy_client_socket_unittest.cc @@ -85,13 +85,13 @@ class SpdyProxyClientSocketTest : public PlatformTest { void AddAuthToCache() { const string16 kFoo(ASCIIToUTF16("foo")); const string16 kBar(ASCIIToUTF16("bar")); - session_->auth_cache()->Add(GURL(kProxyUrl), - "MyRealm1", - HttpAuth::AUTH_SCHEME_BASIC, - "Basic realm=MyRealm1", - kFoo, - kBar, - "/"); + session_->http_auth_cache()->Add(GURL(kProxyUrl), + "MyRealm1", + HttpAuth::AUTH_SCHEME_BASIC, + "Basic realm=MyRealm1", + kFoo, + kBar, + "/"); } void Run(int steps) { @@ -175,7 +175,6 @@ void SpdyProxyClientSocketTest::Initialize(MockRead* reads, // Creates a new spdy session spdy_session_ = session_->spdy_session_pool()->Get(endpoint_host_port_proxy_pair_, - session_->mutable_spdy_settings(), BoundNetLog()); // Perform the TCP connect @@ -196,7 +195,7 @@ void SpdyProxyClientSocketTest::Initialize(MockRead* reads, sock_.reset( new SpdyProxyClientSocket(spdy_stream_, user_agent_, endpoint_host_port_pair_, url_, - proxy_host_port_, session_->auth_cache(), + proxy_host_port_, session_->http_auth_cache(), session_->http_auth_handler_factory())); } diff --git a/net/spdy/spdy_session_pool.cc b/net/spdy/spdy_session_pool.cc index f4ec575..b32495e 100644 --- a/net/spdy/spdy_session_pool.cc +++ b/net/spdy/spdy_session_pool.cc @@ -34,7 +34,6 @@ SpdySessionPool::~SpdySessionPool() { scoped_refptr<SpdySession> SpdySessionPool::Get( const HostPortProxyPair& host_port_proxy_pair, - SpdySettingsStorage* spdy_settings, const BoundNetLog& net_log) { scoped_refptr<SpdySession> spdy_session; SpdySessionList* list = GetSessionList(host_port_proxy_pair); @@ -53,7 +52,7 @@ scoped_refptr<SpdySession> SpdySessionPool::Get( DCHECK(list); if (!spdy_session) { - spdy_session = new SpdySession(host_port_proxy_pair, this, spdy_settings, + spdy_session = new SpdySession(host_port_proxy_pair, this, &spdy_settings_, net_log.net_log()); net_log.AddEvent( NetLog::TYPE_SPDY_SESSION_POOL_CREATED_NEW_SESSION, @@ -69,14 +68,13 @@ scoped_refptr<SpdySession> SpdySessionPool::Get( net::Error SpdySessionPool::GetSpdySessionFromSocket( const HostPortProxyPair& host_port_proxy_pair, - SpdySettingsStorage* spdy_settings, ClientSocketHandle* connection, const BoundNetLog& net_log, int certificate_error_code, scoped_refptr<SpdySession>* spdy_session, bool is_secure) { // Create the SPDY session and add it to the pool. - *spdy_session = new SpdySession(host_port_proxy_pair, this, spdy_settings, + *spdy_session = new SpdySession(host_port_proxy_pair, this, &spdy_settings_, net_log.net_log()); SpdySessionList* list = GetSessionList(host_port_proxy_pair); if (!list) diff --git a/net/spdy/spdy_session_pool.h b/net/spdy/spdy_session_pool.h index 7f30b20..10da747 100644 --- a/net/spdy/spdy_session_pool.h +++ b/net/spdy/spdy_session_pool.h @@ -20,6 +20,7 @@ #include "net/base/ssl_config_service.h" #include "net/proxy/proxy_config.h" #include "net/proxy/proxy_server.h" +#include "net/spdy/spdy_settings_storage.h" namespace net { // Sessions are uniquely identified by their HostPortPair and the proxy server @@ -30,7 +31,6 @@ class BoundNetLog; class ClientSocketHandle; class HttpNetworkSession; class SpdySession; -class SpdySettingsStorage; // This is a very simple pool for open SpdySessions. // TODO(mbelshe): Make this production ready. @@ -45,7 +45,6 @@ class SpdySessionPool // use. scoped_refptr<SpdySession> Get( const HostPortProxyPair& host_port_proxy_pair, - SpdySettingsStorage* spdy_settings, const BoundNetLog& net_log); // Set the maximum concurrent sessions per domain. @@ -66,7 +65,6 @@ class SpdySessionPool // Returns an error on failure, and |spdy_session| will be NULL. net::Error GetSpdySessionFromSocket( const HostPortProxyPair& host_port_proxy_pair, - SpdySettingsStorage* spdy_settings, ClientSocketHandle* connection, const BoundNetLog& net_log, int certificate_error_code, @@ -92,6 +90,9 @@ class SpdySessionPool // responsible for deleting the returned value. Value* SpdySessionPoolInfoToValue() const; + SpdySettingsStorage* mutable_spdy_settings() { return &spdy_settings_; } + const SpdySettingsStorage& spdy_settings() const { return spdy_settings_; } + // NetworkChangeNotifier::Observer methods: // We flush all idle sessions and release references to the active ones so @@ -124,6 +125,8 @@ class SpdySessionPool const HostPortProxyPair& host_port_proxy_pair) const; void RemoveSessionList(const HostPortProxyPair& host_port_proxy_pair); + SpdySettingsStorage spdy_settings_; + // This is our weak session pool - one session per domain. SpdySessionsMap sessions_; diff --git a/net/spdy/spdy_session_unittest.cc b/net/spdy/spdy_session_unittest.cc index 44848e3..0f3b601 100644 --- a/net/spdy/spdy_session_unittest.cc +++ b/net/spdy/spdy_session_unittest.cc @@ -88,8 +88,7 @@ TEST_F(SpdySessionTest, GoAway) { SpdySessionPool* spdy_session_pool(http_session->spdy_session_pool()); EXPECT_FALSE(spdy_session_pool->HasSession(pair)); scoped_refptr<SpdySession> session = - spdy_session_pool->Get(pair, http_session->mutable_spdy_settings(), - BoundNetLog()); + spdy_session_pool->Get(pair, BoundNetLog()); EXPECT_TRUE(spdy_session_pool->HasSession(pair)); scoped_refptr<TCPSocketParams> tcp_params( @@ -107,8 +106,7 @@ TEST_F(SpdySessionTest, GoAway) { EXPECT_FALSE(spdy_session_pool->HasSession(pair)); scoped_refptr<SpdySession> session2 = - spdy_session_pool->Get(pair, http_session->mutable_spdy_settings(), - BoundNetLog()); + spdy_session_pool->Get(pair, BoundNetLog()); // Delete the first session. session = NULL; @@ -187,18 +185,17 @@ TEST_F(SpdySessionTest, OnSettings) { HostPortProxyPair pair(test_host_port_pair, ProxyServer::Direct()); // Initialize the SpdySettingsStorage with 1 max concurrent streams. + SpdySessionPool* spdy_session_pool(http_session->spdy_session_pool()); spdy::SpdySettings old_settings; id.set_flags(spdy::SETTINGS_FLAG_PLEASE_PERSIST); old_settings.push_back(spdy::SpdySetting(id, 1)); - http_session->mutable_spdy_settings()->Set( + spdy_session_pool->mutable_spdy_settings()->Set( test_host_port_pair, old_settings); // Create a session. - SpdySessionPool* spdy_session_pool(http_session->spdy_session_pool()); EXPECT_FALSE(spdy_session_pool->HasSession(pair)); scoped_refptr<SpdySession> session = - spdy_session_pool->Get(pair, http_session->mutable_spdy_settings(), - BoundNetLog()); + spdy_session_pool->Get(pair, BoundNetLog()); ASSERT_TRUE(spdy_session_pool->HasSession(pair)); scoped_refptr<TCPSocketParams> tcp_params( @@ -267,19 +264,19 @@ TEST_F(SpdySessionTest, CancelPendingCreateStream) { HostPortProxyPair pair(test_host_port_pair, ProxyServer::Direct()); // Initialize the SpdySettingsStorage with 1 max concurrent streams. + SpdySessionPool* spdy_session_pool(http_session->spdy_session_pool()); spdy::SpdySettings settings; spdy::SettingsFlagsAndId id(spdy::SETTINGS_MAX_CONCURRENT_STREAMS); id.set_id(spdy::SETTINGS_MAX_CONCURRENT_STREAMS); id.set_flags(spdy::SETTINGS_FLAG_PLEASE_PERSIST); settings.push_back(spdy::SpdySetting(id, 1)); - http_session->mutable_spdy_settings()->Set(test_host_port_pair, settings); + spdy_session_pool->mutable_spdy_settings()->Set( + test_host_port_pair, settings); // Create a session. - SpdySessionPool* spdy_session_pool(http_session->spdy_session_pool()); EXPECT_FALSE(spdy_session_pool->HasSession(pair)); scoped_refptr<SpdySession> session = - spdy_session_pool->Get(pair, http_session->mutable_spdy_settings(), - BoundNetLog()); + spdy_session_pool->Get(pair, BoundNetLog()); ASSERT_TRUE(spdy_session_pool->HasSession(pair)); scoped_refptr<TCPSocketParams> tcp_params( @@ -369,12 +366,12 @@ TEST_F(SpdySessionTest, SendSettingsOnNewSession) { id.set_flags(spdy::SETTINGS_FLAG_PLEASE_PERSIST); settings.clear(); settings.push_back(spdy::SpdySetting(id, kBogusSettingValue)); - http_session->mutable_spdy_settings()->Set(test_host_port_pair, settings); SpdySessionPool* spdy_session_pool(http_session->spdy_session_pool()); + spdy_session_pool->mutable_spdy_settings()->Set( + test_host_port_pair, settings); EXPECT_FALSE(spdy_session_pool->HasSession(pair)); scoped_refptr<SpdySession> session = - spdy_session_pool->Get(pair, http_session->mutable_spdy_settings(), - BoundNetLog()); + spdy_session_pool->Get(pair, BoundNetLog()); EXPECT_TRUE(spdy_session_pool->HasSession(pair)); scoped_refptr<TCPSocketParams> tcp_params( diff --git a/net/spdy/spdy_stream_unittest.cc b/net/spdy/spdy_stream_unittest.cc index 9c7b934..532c79f 100644 --- a/net/spdy/spdy_stream_unittest.cc +++ b/net/spdy/spdy_stream_unittest.cc @@ -117,9 +117,7 @@ class SpdyStreamTest : public testing::Test { HostPortPair host_port_pair("www.google.com", 80); HostPortProxyPair pair(host_port_pair, ProxyServer::Direct()); scoped_refptr<SpdySession> session( - session_->spdy_session_pool()->Get(pair, - session_->mutable_spdy_settings(), - BoundNetLog())); + session_->spdy_session_pool()->Get(pair, BoundNetLog())); return session; } |