diff options
author | rtenneti@chromium.org <rtenneti@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-10-09 02:01:54 +0000 |
---|---|---|
committer | rtenneti@chromium.org <rtenneti@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-10-09 02:01:54 +0000 |
commit | db96a88617afc0e619c06234bd4f4670ccfe1ae3 (patch) | |
tree | d31503fd03c1726882c8ce9eb1fc3338cf966809 /net/http | |
parent | b7333cbad3132c305a3c0032d16b5655bef5fc8b (diff) | |
download | chromium_src-db96a88617afc0e619c06234bd4f4670ccfe1ae3.zip chromium_src-db96a88617afc0e619c06234bd4f4670ccfe1ae3.tar.gz chromium_src-db96a88617afc0e619c06234bd4f4670ccfe1ae3.tar.bz2 |
Introduce net::HttpServerPropertiesManager to manage server-specific properties.
Currently the only property we manage is whether or not a server supports SPDY, as indicated by NPN. Also introduce a chrome/ implementation of HttpServerPropertiesManager that persists the information to Prefererences.
When we get a SpdySession for a SPDY server, record that that server supports SPDY in HttpServerPropertiesManager. When preconnecting, if we know that the server supports SPDY, only preconnect 1 socket.
R=willchan
BUG=66472
TEST=browser ui and unit tests,network unit tests
Review URL: http://codereview.chromium.org/7827033
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@104666 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/http')
-rw-r--r-- | net/http/http_cache.cc | 4 | ||||
-rw-r--r-- | net/http/http_cache.h | 2 | ||||
-rw-r--r-- | net/http/http_network_session.cc | 1 | ||||
-rw-r--r-- | net/http/http_network_session.h | 7 | ||||
-rw-r--r-- | net/http/http_server_properties.h | 42 | ||||
-rw-r--r-- | net/http/http_server_properties_impl.cc | 93 | ||||
-rw-r--r-- | net/http/http_server_properties_impl.h | 66 | ||||
-rw-r--r-- | net/http/http_server_properties_impl_unittest.cc | 186 | ||||
-rw-r--r-- | net/http/http_stream_factory_impl_job.cc | 18 |
9 files changed, 418 insertions, 1 deletions
diff --git a/net/http/http_cache.cc b/net/http/http_cache.cc index 9a23aab..23002d8 100644 --- a/net/http/http_cache.cc +++ b/net/http/http_cache.cc @@ -51,6 +51,7 @@ HttpNetworkSession* CreateNetworkSession( SSLConfigService* ssl_config_service, HttpAuthHandlerFactory* http_auth_handler_factory, NetworkDelegate* network_delegate, + HttpServerProperties* http_server_properties, NetLog* net_log) { HttpNetworkSession::Params params; params.host_resolver = host_resolver; @@ -63,6 +64,7 @@ HttpNetworkSession* CreateNetworkSession( params.ssl_config_service = ssl_config_service; params.http_auth_handler_factory = http_auth_handler_factory; params.network_delegate = network_delegate; + params.http_server_properties = http_server_properties; params.net_log = net_log; return new HttpNetworkSession(params); } @@ -321,6 +323,7 @@ HttpCache::HttpCache(HostResolver* host_resolver, SSLConfigService* ssl_config_service, HttpAuthHandlerFactory* http_auth_handler_factory, NetworkDelegate* network_delegate, + HttpServerProperties* http_server_properties, NetLog* net_log, BackendFactory* backend_factory) : net_log_(net_log), @@ -343,6 +346,7 @@ HttpCache::HttpCache(HostResolver* host_resolver, ssl_config_service, http_auth_handler_factory, network_delegate, + http_server_properties, net_log))), ALLOW_THIS_IN_INITIALIZER_LIST(task_factory_(this)) { } diff --git a/net/http/http_cache.h b/net/http/http_cache.h index f6b7ffe..1a7a51d 100644 --- a/net/http/http_cache.h +++ b/net/http/http_cache.h @@ -51,6 +51,7 @@ class HttpAuthHandlerFactory; class HttpNetworkSession; struct HttpRequestInfo; class HttpResponseInfo; +class HttpServerProperties; class IOBuffer; class NetLog; class NetworkDelegate; @@ -129,6 +130,7 @@ class NET_EXPORT HttpCache : public HttpTransactionFactory, SSLConfigService* ssl_config_service, HttpAuthHandlerFactory* http_auth_handler_factory, NetworkDelegate* network_delegate, + HttpServerProperties* http_server_properties, NetLog* net_log, BackendFactory* backend_factory); diff --git a/net/http/http_network_session.cc b/net/http/http_network_session.cc index b5a104d..5fed4bf 100644 --- a/net/http/http_network_session.cc +++ b/net/http/http_network_session.cc @@ -25,6 +25,7 @@ namespace net { HttpNetworkSession::HttpNetworkSession(const Params& params) : net_log_(params.net_log), network_delegate_(params.network_delegate), + http_server_properties_(params.http_server_properties), cert_verifier_(params.cert_verifier), http_auth_handler_factory_(params.http_auth_handler_factory), proxy_service_(params.proxy_service), diff --git a/net/http/http_network_session.h b/net/http/http_network_session.h index d4e391e..777653b 100644 --- a/net/http/http_network_session.h +++ b/net/http/http_network_session.h @@ -35,6 +35,7 @@ class HttpAuthHandlerFactory; class HttpNetworkSessionPeer; class HttpProxyClientSocketPool; class HttpResponseBodyDrainer; +class HttpServerProperties; class NetLog; class NetworkDelegate; class ProxyService; @@ -59,6 +60,7 @@ class NET_EXPORT HttpNetworkSession ssl_config_service(NULL), http_auth_handler_factory(NULL), network_delegate(NULL), + http_server_properties(NULL), net_log(NULL) {} ClientSocketFactory* client_socket_factory; @@ -72,6 +74,7 @@ class NET_EXPORT HttpNetworkSession SSLConfigService* ssl_config_service; HttpAuthHandlerFactory* http_auth_handler_factory; NetworkDelegate* network_delegate; + HttpServerProperties* http_server_properties; NetLog* net_log; }; @@ -120,6 +123,9 @@ class NET_EXPORT HttpNetworkSession NetworkDelegate* network_delegate() { return network_delegate_; } + HttpServerProperties* http_server_properties() { + return http_server_properties_; + } HttpStreamFactory* http_stream_factory() { return http_stream_factory_.get(); @@ -148,6 +154,7 @@ class NET_EXPORT HttpNetworkSession NetLog* const net_log_; NetworkDelegate* const network_delegate_; + HttpServerProperties* const http_server_properties_; CertVerifier* const cert_verifier_; HttpAuthHandlerFactory* const http_auth_handler_factory_; diff --git a/net/http/http_server_properties.h b/net/http/http_server_properties.h new file mode 100644 index 0000000..a8dc6bf --- /dev/null +++ b/net/http/http_server_properties.h @@ -0,0 +1,42 @@ +// 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_SERVER_PROPERTIES_H_ +#define NET_HTTP_HTTP_SERVER_PROPERTIES_H_ + +#include <string> +#include <vector> + +#include "base/basictypes.h" +#include "net/base/host_port_pair.h" +#include "net/base/net_export.h" + +namespace net { + +// The interface for setting/retrieving the HTTP server properties. +class NET_EXPORT HttpServerProperties { + public: + typedef std::vector<std::string> StringVector; + + HttpServerProperties() {} + virtual ~HttpServerProperties() {} + + // Returns true if |server| supports SPDY. + virtual bool SupportsSpdy(const HostPortPair& server) const = 0; + + // Add |server| into the persistent store. Should only be called from IO + // thread. + virtual void SetSupportsSpdy(const HostPortPair& server, + bool support_spdy) = 0; + + // Deletes all data. + virtual void DeleteAll() = 0; + + private: + DISALLOW_COPY_AND_ASSIGN(HttpServerProperties); +}; + +} // namespace net + +#endif // NET_HTTP_HTTP_SERVER_PROPERTIES_H_ diff --git a/net/http/http_server_properties_impl.cc b/net/http/http_server_properties_impl.cc new file mode 100644 index 0000000..9dd341d --- /dev/null +++ b/net/http/http_server_properties_impl.cc @@ -0,0 +1,93 @@ +// 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_server_properties_impl.h" + +#include "base/logging.h" +#include "base/memory/scoped_ptr.h" +#include "base/stl_util.h" +#include "base/stringprintf.h" + +namespace net { + +HttpServerPropertiesImpl::HttpServerPropertiesImpl() { +} + +HttpServerPropertiesImpl::~HttpServerPropertiesImpl() { +} + +void HttpServerPropertiesImpl::Initialize(StringVector* spdy_servers, + bool support_spdy) { + DCHECK(CalledOnValidThread()); + spdy_servers_table_.clear(); + if (!spdy_servers) + return; + for (StringVector::iterator it = spdy_servers->begin(); + it != spdy_servers->end(); ++it) { + spdy_servers_table_[*it] = support_spdy; + } +} + +bool HttpServerPropertiesImpl::SupportsSpdy( + const net::HostPortPair& host_port_pair) const { + DCHECK(CalledOnValidThread()); + if (host_port_pair.host().empty()) + return false; + std::string spdy_server = GetFlattenedSpdyServer(host_port_pair); + + SpdyServerHostPortTable::const_iterator spdy_host_port = + spdy_servers_table_.find(spdy_server); + if (spdy_host_port != spdy_servers_table_.end()) + return spdy_host_port->second; + return false; +} + +void HttpServerPropertiesImpl::SetSupportsSpdy( + const net::HostPortPair& host_port_pair, + bool support_spdy) { + DCHECK(CalledOnValidThread()); + if (host_port_pair.host().empty()) + return; + std::string spdy_server = GetFlattenedSpdyServer(host_port_pair); + + SpdyServerHostPortTable::iterator spdy_host_port = + spdy_servers_table_.find(spdy_server); + if ((spdy_host_port != spdy_servers_table_.end()) && + (spdy_host_port->second == support_spdy)) { + return; + } + // Cache the data. + spdy_servers_table_[spdy_server] = support_spdy; +} + +void HttpServerPropertiesImpl::DeleteAll() { + DCHECK(CalledOnValidThread()); + spdy_servers_table_.clear(); +} + +void HttpServerPropertiesImpl::GetSpdyServerList( + base::ListValue* spdy_server_list) const { + DCHECK(CalledOnValidThread()); + DCHECK(spdy_server_list); + spdy_server_list->Clear(); + // Get the list of servers (host/port) that support SPDY. + for (SpdyServerHostPortTable::const_iterator it = spdy_servers_table_.begin(); + it != spdy_servers_table_.end(); ++it) { + const std::string spdy_server_host_port = it->first; + if (it->second) + spdy_server_list->Append(new StringValue(spdy_server_host_port)); + } +} + +// static +std::string HttpServerPropertiesImpl::GetFlattenedSpdyServer( + const net::HostPortPair& host_port_pair) { + std::string spdy_server; + spdy_server.append(host_port_pair.host()); + spdy_server.append(":"); + base::StringAppendF(&spdy_server, "%d", host_port_pair.port()); + return spdy_server; +} + +} // namespace net diff --git a/net/http/http_server_properties_impl.h b/net/http/http_server_properties_impl.h new file mode 100644 index 0000000..a18b05c --- /dev/null +++ b/net/http/http_server_properties_impl.h @@ -0,0 +1,66 @@ +// 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_SERVER_PROPERTIES_IMPL_H_ +#define NET_HTTP_HTTP_SERVER_PROPERTIES_IMPL_H_ + +#include <string> + +#include "base/basictypes.h" +#include "base/gtest_prod_util.h" +#include "base/hash_tables.h" +#include "base/threading/non_thread_safe.h" +#include "base/values.h" +#include "net/base/host_port_pair.h" +#include "net/base/net_export.h" +#include "net/http/http_server_properties.h" + +namespace base { +class ListValue; +} + +namespace net { + +// The implementation for setting/retrieving the HTTP server properties. +class NET_EXPORT HttpServerPropertiesImpl + : public HttpServerProperties, + NON_EXPORTED_BASE(public base::NonThreadSafe) { + public: + HttpServerPropertiesImpl(); + virtual ~HttpServerPropertiesImpl(); + + // Initializes |spdy_servers_table_| with the servers (host/port) from + // |spdy_servers| that either support SPDY or not. + void Initialize(StringVector* spdy_servers, bool support_spdy); + + // Returns true if |server| supports SPDY. + virtual bool SupportsSpdy(const HostPortPair& server) const OVERRIDE; + + // Add |server| into the persistent store. + virtual void SetSupportsSpdy(const HostPortPair& server, + bool support_spdy) OVERRIDE; + + // Deletes all data. + virtual void DeleteAll() OVERRIDE; + + // Get the list of servers (host/port) that support SPDY. + void GetSpdyServerList(base::ListValue* spdy_server_list) const; + + // Returns flattened string representation of the |host_port_pair|. Used by + // unittests. + static std::string GetFlattenedSpdyServer( + const net::HostPortPair& host_port_pair); + + private: + // |spdy_servers_table_| has flattened representation of servers (host/port + // pair) that either support or not support SPDY protocol. + typedef base::hash_map<std::string, bool> SpdyServerHostPortTable; + SpdyServerHostPortTable spdy_servers_table_; + + DISALLOW_COPY_AND_ASSIGN(HttpServerPropertiesImpl); +}; + +} // namespace net + +#endif // NET_HTTP_HTTP_SERVER_PROPERTIES_IMPL_H_ diff --git a/net/http/http_server_properties_impl_unittest.cc b/net/http/http_server_properties_impl_unittest.cc new file mode 100644 index 0000000..a9f556c --- /dev/null +++ b/net/http/http_server_properties_impl_unittest.cc @@ -0,0 +1,186 @@ +// 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_server_properties_impl.h" + +#include <string> + +#include "base/basictypes.h" +#include "base/hash_tables.h" +#include "base/logging.h" +#include "base/memory/scoped_ptr.h" +#include "base/values.h" +#include "net/base/host_port_pair.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace base { +class ListValue; +} + +namespace net { + +namespace { + +class HttpServerPropertiesImplTest : public testing::Test { + protected: + HttpServerPropertiesImpl impl_; +}; + +TEST_F(HttpServerPropertiesImplTest, InitializeTest) { + HostPortPair spdy_server_google("www.google.com", 443); + std::string spdy_server_g = + HttpServerPropertiesImpl::GetFlattenedSpdyServer(spdy_server_google); + + HostPortPair spdy_server_docs("docs.google.com", 443); + std::string spdy_server_d = + HttpServerPropertiesImpl::GetFlattenedSpdyServer(spdy_server_docs); + + // Check by initializing NULL spdy servers. + impl_.Initialize(NULL, true); + EXPECT_FALSE(impl_.SupportsSpdy(spdy_server_google)); + + // Check by initializing empty spdy servers. + HttpServerProperties::StringVector spdy_servers; + impl_.Initialize(&spdy_servers, true); + EXPECT_FALSE(impl_.SupportsSpdy(spdy_server_google)); + + // Check by initializing with www.google.com:443 spdy server. + HttpServerProperties::StringVector spdy_servers1; + spdy_servers1.push_back(spdy_server_g); + impl_.Initialize(&spdy_servers1, true); + EXPECT_TRUE(impl_.SupportsSpdy(spdy_server_google)); + + // Check by initializing with www.google.com:443 and docs.google.com:443 spdy + // servers. + HttpServerProperties::StringVector spdy_servers2; + spdy_servers2.push_back(spdy_server_g); + spdy_servers2.push_back(spdy_server_d); + impl_.Initialize(&spdy_servers2, true); + EXPECT_TRUE(impl_.SupportsSpdy(spdy_server_google)); + EXPECT_TRUE(impl_.SupportsSpdy(spdy_server_docs)); +} + +TEST_F(HttpServerPropertiesImplTest, SupportsSpdyTest) { + HostPortPair spdy_server_empty("", 443); + EXPECT_FALSE(impl_.SupportsSpdy(spdy_server_empty)); + + // Add www.google.com:443 as supporting SPDY. + HostPortPair spdy_server_google("www.google.com", 443); + impl_.SetSupportsSpdy(spdy_server_google, true); + EXPECT_TRUE(impl_.SupportsSpdy(spdy_server_google)); + + // Add mail.google.com:443 as not supporting SPDY. + HostPortPair spdy_server_mail("mail.google.com", 443); + EXPECT_FALSE(impl_.SupportsSpdy(spdy_server_mail)); + + // Add docs.google.com:443 as supporting SPDY. + HostPortPair spdy_server_docs("docs.google.com", 443); + impl_.SetSupportsSpdy(spdy_server_docs, true); + EXPECT_TRUE(impl_.SupportsSpdy(spdy_server_docs)); + + // Verify all the entries are the same after additions. + EXPECT_TRUE(impl_.SupportsSpdy(spdy_server_google)); + EXPECT_FALSE(impl_.SupportsSpdy(spdy_server_mail)); + EXPECT_TRUE(impl_.SupportsSpdy(spdy_server_docs)); +} + +TEST_F(HttpServerPropertiesImplTest, SetSupportsSpdyTest) { + HostPortPair spdy_server_empty("", 443); + impl_.SetSupportsSpdy(spdy_server_empty, true); + EXPECT_FALSE(impl_.SupportsSpdy(spdy_server_empty)); + + // Add www.google.com:443 as supporting SPDY. + HostPortPair spdy_server_google("www.google.com", 443); + EXPECT_FALSE(impl_.SupportsSpdy(spdy_server_google)); + impl_.SetSupportsSpdy(spdy_server_google, true); + EXPECT_TRUE(impl_.SupportsSpdy(spdy_server_google)); + + // Make www.google.com:443 as not supporting SPDY. + impl_.SetSupportsSpdy(spdy_server_google, false); + EXPECT_FALSE(impl_.SupportsSpdy(spdy_server_google)); + + // Add mail.google.com:443 as supporting SPDY. + HostPortPair spdy_server_mail("mail.google.com", 443); + EXPECT_FALSE(impl_.SupportsSpdy(spdy_server_mail)); + impl_.SetSupportsSpdy(spdy_server_mail, true); + EXPECT_TRUE(impl_.SupportsSpdy(spdy_server_mail)); + EXPECT_FALSE(impl_.SupportsSpdy(spdy_server_google)); +} + +TEST_F(HttpServerPropertiesImplTest, DeleteAllTest) { + // Add www.google.com:443 and mail.google.com:443 as supporting SPDY. + HostPortPair spdy_server_google("www.google.com", 443); + impl_.SetSupportsSpdy(spdy_server_google, true); + HostPortPair spdy_server_mail("mail.google.com", 443); + impl_.SetSupportsSpdy(spdy_server_mail, true); + + EXPECT_TRUE(impl_.SupportsSpdy(spdy_server_google)); + EXPECT_TRUE(impl_.SupportsSpdy(spdy_server_mail)); + + impl_.DeleteAll(); + EXPECT_FALSE(impl_.SupportsSpdy(spdy_server_google)); + EXPECT_FALSE(impl_.SupportsSpdy(spdy_server_mail)); +} + +TEST_F(HttpServerPropertiesImplTest, GetSpdyServerListTest) { + base::ListValue spdy_server_list; + + // Check there are no spdy_servers. + impl_.GetSpdyServerList(&spdy_server_list); + EXPECT_EQ(0u, spdy_server_list.GetSize()); + + // Check empty server is not added. + HostPortPair spdy_server_empty("", 443); + impl_.SetSupportsSpdy(spdy_server_empty, true); + impl_.GetSpdyServerList(&spdy_server_list); + EXPECT_EQ(0u, spdy_server_list.GetSize()); + + std::string string_value_g; + std::string string_value_m; + HostPortPair spdy_server_google("www.google.com", 443); + std::string spdy_server_g = + HttpServerPropertiesImpl::GetFlattenedSpdyServer(spdy_server_google); + HostPortPair spdy_server_mail("mail.google.com", 443); + std::string spdy_server_m = + HttpServerPropertiesImpl::GetFlattenedSpdyServer(spdy_server_mail); + + // Add www.google.com:443 as not supporting SPDY. + impl_.SetSupportsSpdy(spdy_server_google, false); + impl_.GetSpdyServerList(&spdy_server_list); + EXPECT_EQ(0u, spdy_server_list.GetSize()); + + // Add www.google.com:443 as supporting SPDY. + impl_.SetSupportsSpdy(spdy_server_google, true); + impl_.GetSpdyServerList(&spdy_server_list); + EXPECT_EQ(1u, spdy_server_list.GetSize()); + ASSERT_TRUE(spdy_server_list.GetString(0, &string_value_g)); + ASSERT_EQ(spdy_server_g, string_value_g); + + // Add mail.google.com:443 as not supporting SPDY. + impl_.SetSupportsSpdy(spdy_server_mail, false); + impl_.GetSpdyServerList(&spdy_server_list); + EXPECT_EQ(1u, spdy_server_list.GetSize()); + ASSERT_TRUE(spdy_server_list.GetString(0, &string_value_g)); + ASSERT_EQ(spdy_server_g, string_value_g); + + // Add mail.google.com:443 as supporting SPDY. + impl_.SetSupportsSpdy(spdy_server_mail, true); + impl_.GetSpdyServerList(&spdy_server_list); + EXPECT_EQ(2u, spdy_server_list.GetSize()); + + // Verify www.google.com:443 and mail.google.com:443 are in the list. + ASSERT_TRUE(spdy_server_list.GetString(0, &string_value_g)); + ASSERT_TRUE(spdy_server_list.GetString(1, &string_value_m)); + if (string_value_g.compare(spdy_server_g) == 0) { + ASSERT_EQ(spdy_server_g, string_value_g); + ASSERT_EQ(spdy_server_m, string_value_m); + } else { + ASSERT_EQ(spdy_server_g, string_value_m); + ASSERT_EQ(spdy_server_m, string_value_g); + } +} + +} // namespace + +} // namespace net diff --git a/net/http/http_stream_factory_impl_job.cc b/net/http/http_stream_factory_impl_job.cc index b55d1ac..f496042 100644 --- a/net/http/http_stream_factory_impl_job.cc +++ b/net/http/http_stream_factory_impl_job.cc @@ -19,6 +19,7 @@ #include "net/http/http_proxy_client_socket.h" #include "net/http/http_proxy_client_socket_pool.h" #include "net/http/http_request_info.h" +#include "net/http/http_server_properties.h" #include "net/http/http_stream_factory_impl_request.h" #include "net/socket/client_socket_handle.h" #include "net/socket/client_socket_pool.h" @@ -119,7 +120,17 @@ void HttpStreamFactoryImpl::Job::Start(Request* request) { int HttpStreamFactoryImpl::Job::Preconnect(int num_streams) { DCHECK_GT(num_streams, 0); - num_streams_ = num_streams; + HostPortPair origin_server = + HostPortPair(request_info_.url.HostNoBrackets(), + request_info_.url.EffectiveIntPort()); + HttpServerProperties* http_server_properties = + session_->http_server_properties(); + if (http_server_properties && + http_server_properties->SupportsSpdy(origin_server)) { + num_streams_ = 1; + } else { + num_streams_ = num_streams; + } return StartInternal(); } @@ -821,6 +832,11 @@ int HttpStreamFactoryImpl::Job::DoCreateStream() { &new_spdy_session_, using_ssl_); if (error != OK) return error; + const HostPortPair& host_port_pair = pair.first; + HttpServerProperties* http_server_properties = + session_->http_server_properties(); + if (http_server_properties) + http_server_properties->SetSupportsSpdy(host_port_pair, true); spdy_session_direct_ = direct; return OK; } |