Merge HttpServerPropertiesImpl into HttpServerProperties.
It's the only implementation (Other than a test-only subclass that this
CL removes).
To avoid a circular dependency, this CL also moves
HttpServerPropertiesManager::PrefDelegate into HttpServerProperties.
[email protected]
[email protected]
Bug: 984996
Change-Id: I00b6d3633b16afb47b5f00738ea0e128f9dc69db
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1724586
Reviewed-by: Matt Menke <[email protected]>
Reviewed-by: Zhongyi Shi <[email protected]>
Commit-Queue: Matt Menke <[email protected]>
Cr-Commit-Position: refs/heads/master@{#683685}
diff --git a/net/http/http_server_properties.h b/net/http/http_server_properties.h
index d5301f7e..43005e7 100644
--- a/net/http/http_server_properties.h
+++ b/net/http/http_server_properties.h
@@ -5,7 +5,12 @@
#ifndef NET_HTTP_HTTP_SERVER_PROPERTIES_H_
#define NET_HTTP_HTTP_SERVER_PROPERTIES_H_
+#include <stddef.h>
+#include <stdint.h>
+
#include <map>
+#include <memory>
+#include <set>
#include <string>
#include <tuple>
#include <vector>
@@ -13,9 +18,17 @@
#include "base/callback.h"
#include "base/containers/mru_cache.h"
#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "base/threading/thread_checker.h"
#include "base/time/time.h"
+#include "base/timer/timer.h"
+#include "base/values.h"
+#include "net/base/host_port_pair.h"
+#include "net/base/ip_address.h"
#include "net/base/net_export.h"
#include "net/http/alternative_service.h"
+#include "net/http/broken_alternative_services.h"
+#include "net/http/http_server_properties.h"
#include "net/third_party/quiche/src/quic/core/quic_bandwidth.h"
#include "net/third_party/quiche/src/quic/core/quic_server_id.h"
#include "net/third_party/quiche/src/quic/core/quic_versions.h"
@@ -24,20 +37,23 @@
#include "url/scheme_host_port.h"
namespace base {
+class Clock;
+class TickClock;
class Value;
}
namespace net {
class HostPortPair;
+class HttpServerPropertiesManager;
class IPAddress;
+class NetLog;
struct SSLConfig;
struct NET_EXPORT SupportsQuic {
SupportsQuic() : used_quic(false) {}
SupportsQuic(bool used_quic, const std::string& address)
- : used_quic(used_quic),
- address(address) {}
+ : used_quic(used_quic), address(address) {}
bool Equals(const SupportsQuic& other) const {
return used_quic == other.used_quic && address == other.address;
@@ -116,71 +132,105 @@
// * Alternative Service support;
// * QUIC data (like ServerNetworkStats and QuicServerInfo).
//
-// Embedders must ensure that HttpServerProperites is completely initialized
-// before the first request is issued.
-class NET_EXPORT HttpServerProperties {
+// Optionally retrieves and saves properties from/to disk.
+class NET_EXPORT HttpServerProperties
+ : public BrokenAlternativeServices::Delegate {
public:
- HttpServerProperties() {}
- virtual ~HttpServerProperties() {}
+ // Provides an interface to interact with persistent preferences storage
+ // implemented by the embedder. The prefs are assumed not to have been loaded
+ // before HttpServerPropertiesManager construction.
+ class NET_EXPORT PrefDelegate {
+ public:
+ virtual ~PrefDelegate();
+
+ // Returns the branch of the preferences system for the server properties.
+ // Returns nullptr if the pref system has no data for the server properties.
+ virtual const base::DictionaryValue* GetServerProperties() const = 0;
+
+ // Sets the server properties to the given value. If |callback| is
+ // non-empty, flushes data to persistent storage and invokes |callback|
+ // asynchronously when complete.
+ virtual void SetServerProperties(const base::DictionaryValue& value,
+ base::OnceClosure callback) = 0;
+
+ // Starts listening for prefs to be loaded. If prefs are already loaded,
+ // |pref_loaded_callback| will be invoked asynchronously. Callback will be
+ // invoked even if prefs fail to load. Will only be called once by the
+ // HttpServerPropertiesManager.
+ virtual void WaitForPrefLoad(base::OnceClosure pref_loaded_callback) = 0;
+ };
+
+ // If a |pref_delegate| is specified, it will be used to read/write the
+ // properties to a pref file. Writes are rate limited to improve performance.
+ //
+ // |tick_clock| is used for setting expiration times and scheduling the
+ // expiration of broken alternative services. If null, default clock will be
+ // used.
+ //
+ // |clock| is used for converting base::TimeTicks to base::Time for
+ // wherever base::Time is preferable.
+ HttpServerProperties(std::unique_ptr<PrefDelegate> pref_delegate = nullptr,
+ NetLog* net_log = nullptr,
+ const base::TickClock* tick_clock = nullptr,
+ base::Clock* clock = nullptr);
+
+ ~HttpServerProperties() override;
// Deletes all data. If |callback| is non-null, flushes data to disk
// and invokes the callback asynchronously once changes have been written to
// disk.
- virtual void Clear(base::OnceClosure callback) = 0;
+ void Clear(base::OnceClosure callback);
// Returns true if |server| supports a network protocol which honors
// request prioritization.
// Note that this also implies that the server supports request
// multiplexing, since priorities imply a relationship between
// multiple requests.
- virtual bool SupportsRequestPriority(const url::SchemeHostPort& server) = 0;
+ bool SupportsRequestPriority(const url::SchemeHostPort& server);
// Returns the value set by SetSupportsSpdy(). If not set, returns false.
- virtual bool GetSupportsSpdy(const url::SchemeHostPort& server) = 0;
+ bool GetSupportsSpdy(const url::SchemeHostPort& server);
// Add |server| into the persistent store. Should only be called from IO
// thread.
- virtual void SetSupportsSpdy(const url::SchemeHostPort& server,
- bool support_spdy) = 0;
+ void SetSupportsSpdy(const url::SchemeHostPort& server, bool support_spdy);
// Returns true if |server| has required HTTP/1.1 via HTTP/2 error code.
- virtual bool RequiresHTTP11(const HostPortPair& server) = 0;
+ bool RequiresHTTP11(const HostPortPair& server);
// Require HTTP/1.1 on subsequent connections. Not persisted.
- virtual void SetHTTP11Required(const HostPortPair& server) = 0;
+ void SetHTTP11Required(const HostPortPair& server);
// Modify SSLConfig to force HTTP/1.1.
static void ForceHTTP11(SSLConfig* ssl_config);
// Modify SSLConfig to force HTTP/1.1 if necessary.
- virtual void MaybeForceHTTP11(const HostPortPair& server,
- SSLConfig* ssl_config) = 0;
+ void MaybeForceHTTP11(const HostPortPair& server, SSLConfig* ssl_config);
// Return all alternative services for |origin|, including broken ones.
// Returned alternative services never have empty hostnames.
- virtual AlternativeServiceInfoVector GetAlternativeServiceInfos(
- const url::SchemeHostPort& origin) = 0;
+ AlternativeServiceInfoVector GetAlternativeServiceInfos(
+ const url::SchemeHostPort& origin);
// Set a single HTTP/2 alternative service for |origin|. Previous
// alternative services for |origin| are discarded.
// |alternative_service.host| may be empty.
// Return true if |alternative_service_map_| has changed significantly enough
// that it should be persisted to disk.
- virtual bool SetHttp2AlternativeService(
- const url::SchemeHostPort& origin,
- const AlternativeService& alternative_service,
- base::Time expiration) = 0;
+ bool SetHttp2AlternativeService(const url::SchemeHostPort& origin,
+ const AlternativeService& alternative_service,
+ base::Time expiration);
// Set a single QUIC alternative service for |origin|. Previous alternative
// services for |origin| are discarded.
// |alternative_service.host| may be empty.
// Return true if |alternative_service_map_| has changed significantly enough
// that it should be persisted to disk.
- virtual bool SetQuicAlternativeService(
+ bool SetQuicAlternativeService(
const url::SchemeHostPort& origin,
const AlternativeService& alternative_service,
base::Time expiration,
- const quic::ParsedQuicVersionVector& advertised_versions) = 0;
+ const quic::ParsedQuicVersionVector& advertised_versions);
// Set alternative services for |origin|. Previous alternative services for
// |origin| are discarded.
@@ -188,97 +238,267 @@
// |alternative_service_info_vector| may be empty.
// Return true if |alternative_service_map_| has changed significantly enough
// that it should be persisted to disk.
- virtual bool SetAlternativeServices(
+ bool SetAlternativeServices(
const url::SchemeHostPort& origin,
- const AlternativeServiceInfoVector& alternative_service_info_vector) = 0;
+ const AlternativeServiceInfoVector& alternative_service_info_vector);
// Marks |alternative_service| as broken.
// |alternative_service.host| must not be empty.
- virtual void MarkAlternativeServiceBroken(
- const AlternativeService& alternative_service) = 0;
+ void MarkAlternativeServiceBroken(
+ const AlternativeService& alternative_service);
// Marks |alternative_service| as broken until the default network changes.
// |alternative_service.host| must not be empty.
- virtual void MarkAlternativeServiceBrokenUntilDefaultNetworkChanges(
- const AlternativeService& alternative_service) = 0;
+ void MarkAlternativeServiceBrokenUntilDefaultNetworkChanges(
+ const AlternativeService& alternative_service);
// Marks |alternative_service| as recently broken.
// |alternative_service.host| must not be empty.
- virtual void MarkAlternativeServiceRecentlyBroken(
- const AlternativeService& alternative_service) = 0;
+ void MarkAlternativeServiceRecentlyBroken(
+ const AlternativeService& alternative_service);
// Returns true iff |alternative_service| is currently broken.
// |alternative_service.host| must not be empty.
- virtual bool IsAlternativeServiceBroken(
- const AlternativeService& alternative_service) const = 0;
+ bool IsAlternativeServiceBroken(
+ const AlternativeService& alternative_service) const;
// Returns true iff |alternative_service| was recently broken.
// |alternative_service.host| must not be empty.
- virtual bool WasAlternativeServiceRecentlyBroken(
- const AlternativeService& alternative_service) = 0;
+ bool WasAlternativeServiceRecentlyBroken(
+ const AlternativeService& alternative_service);
// Confirms that |alternative_service| is working.
// |alternative_service.host| must not be empty.
- virtual void ConfirmAlternativeService(
- const AlternativeService& alternative_service) = 0;
+ void ConfirmAlternativeService(const AlternativeService& alternative_service);
// Called when the default network changes.
// Clears all the alternative services that were marked broken until the
// default network changed.
// Returns true if there is any broken alternative service affected by the
// default network change.
- virtual bool OnDefaultNetworkChanged() = 0;
+ bool OnDefaultNetworkChanged();
// Returns all alternative service mappings.
// Returned alternative services may have empty hostnames.
- virtual const AlternativeServiceMap& alternative_service_map() const = 0;
+ const AlternativeServiceMap& alternative_service_map() const;
// Returns all alternative service mappings as human readable strings.
// Empty alternative service hostnames will be printed as such.
- virtual std::unique_ptr<base::Value> GetAlternativeServiceInfoAsValue()
- const = 0;
+ std::unique_ptr<base::Value> GetAlternativeServiceInfoAsValue() const;
- virtual bool GetSupportsQuic(IPAddress* last_address) const = 0;
+ bool GetSupportsQuic(IPAddress* last_address) const;
- virtual void SetSupportsQuic(bool used_quic,
- const IPAddress& last_address) = 0;
+ void SetSupportsQuic(bool used_quic, const IPAddress& last_address);
// Sets |stats| for |server|.
- virtual void SetServerNetworkStats(const url::SchemeHostPort& server,
- ServerNetworkStats stats) = 0;
+ void SetServerNetworkStats(const url::SchemeHostPort& server,
+ ServerNetworkStats stats);
// Clears any stats for |server|.
- virtual void ClearServerNetworkStats(const url::SchemeHostPort& server) = 0;
+ void ClearServerNetworkStats(const url::SchemeHostPort& server);
// Returns any stats for |server| or nullptr if there are none.
- virtual const ServerNetworkStats* GetServerNetworkStats(
- const url::SchemeHostPort& server) = 0;
+ const ServerNetworkStats* GetServerNetworkStats(
+ const url::SchemeHostPort& server);
- virtual const ServerNetworkStatsMap& server_network_stats_map() const = 0;
+ const ServerNetworkStatsMap& server_network_stats_map() const;
// Save QuicServerInfo (in std::string form) for the given |server_id|.
// Returns true if the value has changed otherwise it returns false.
- virtual bool SetQuicServerInfo(const quic::QuicServerId& server_id,
- const std::string& server_info) = 0;
+ bool SetQuicServerInfo(const quic::QuicServerId& server_id,
+ const std::string& server_info);
// Get QuicServerInfo (in std::string form) for the given |server_id|.
- virtual const std::string* GetQuicServerInfo(
- const quic::QuicServerId& server_id) = 0;
+ const std::string* GetQuicServerInfo(const quic::QuicServerId& server_id);
// Returns all persistent QuicServerInfo objects.
- virtual const QuicServerInfoMap& quic_server_info_map() const = 0;
+ const QuicServerInfoMap& quic_server_info_map() const;
// Returns the number of server configs (QuicServerInfo objects) persisted.
- virtual size_t max_server_configs_stored_in_properties() const = 0;
+ size_t max_server_configs_stored_in_properties() const;
// Sets the number of server configs (QuicServerInfo objects) to be persisted.
- virtual void SetMaxServerConfigsStoredInProperties(
- size_t max_server_configs_stored_in_properties) = 0;
+ void SetMaxServerConfigsStoredInProperties(
+ size_t max_server_configs_stored_in_properties);
// Returns whether HttpServerProperties is initialized.
- virtual bool IsInitialized() const = 0;
+ bool IsInitialized() const;
+
+ // BrokenAlternativeServices::Delegate method.
+ void OnExpireBrokenAlternativeService(
+ const AlternativeService& expired_alternative_service) override;
+
+ static base::TimeDelta GetUpdatePrefsDelayForTesting();
+
+ // Test-only routines that call the methods used to load the specified
+ // field(s) from a prefs file. Unlike OnPrefsLoaded(), these may be invoked
+ // multiple times.
+ void OnSpdyServersLoadedForTesting(
+ std::unique_ptr<SpdyServersMap> spdy_servers_map) {
+ OnSpdyServersLoaded(std::move(spdy_servers_map));
+ }
+ void OnAlternativeServiceServersLoadedForTesting(
+ std::unique_ptr<AlternativeServiceMap> alternate_protocol_servers) {
+ OnAlternativeServiceServersLoaded(std::move(alternate_protocol_servers));
+ }
+ void OnServerNetworkStatsLoadedForTesting(
+ std::unique_ptr<ServerNetworkStatsMap> server_network_stats_map) {
+ OnServerNetworkStatsLoaded(std::move(server_network_stats_map));
+ }
+ void OnSupportsQuicLoadedForTesting(const IPAddress& last_address) {
+ OnSupportsQuicLoaded(last_address);
+ }
+ void OnQuicServerInfoMapLoadedForTesting(
+ std::unique_ptr<QuicServerInfoMap> quic_server_info_map) {
+ OnQuicServerInfoMapLoaded(std::move(quic_server_info_map));
+ }
+ void OnBrokenAndRecentlyBrokenAlternativeServicesLoadedForTesting(
+ std::unique_ptr<BrokenAlternativeServiceList>
+ broken_alternative_service_list,
+ std::unique_ptr<RecentlyBrokenAlternativeServices>
+ recently_broken_alternative_services) {
+ OnBrokenAndRecentlyBrokenAlternativeServicesLoaded(
+ std::move(broken_alternative_service_list),
+ std::move(recently_broken_alternative_services));
+ }
+
+ const std::string* GetCanonicalSuffixForTesting(
+ const std::string& host) const {
+ return GetCanonicalSuffix(host);
+ }
+
+ const SpdyServersMap& spdy_servers_map_for_testing() const {
+ return spdy_servers_map_;
+ }
+
+ // TODO(mmenke): Look into removing this.
+ HttpServerPropertiesManager* properties_manager_for_testing() {
+ return properties_manager_.get();
+ }
private:
+ // TODO (wangyix): modify HttpServerProperties unit tests so this
+ // friendness is no longer required.
+ friend class HttpServerPropertiesPeer;
+
+ typedef base::flat_map<url::SchemeHostPort, url::SchemeHostPort>
+ CanonicalAltSvcMap;
+ typedef base::flat_map<HostPortPair, quic::QuicServerId>
+ CanonicalServerInfoMap;
+ typedef std::vector<std::string> CanonicalSuffixList;
+ typedef std::set<HostPortPair> Http11ServerHostPortSet;
+
+ // Return the iterator for |server|, or for its canonical host, or end.
+ AlternativeServiceMap::const_iterator GetAlternateProtocolIterator(
+ const url::SchemeHostPort& server);
+
+ // Return the canonical host for |server|, or end if none exists.
+ CanonicalAltSvcMap::const_iterator GetCanonicalAltSvcHost(
+ const url::SchemeHostPort& server) const;
+
+ // Return the canonical host with the same canonical suffix as |server|.
+ // The returned canonical host can be used to search for server info in
+ // |quic_server_info_map_|. Return 'end' the host doesn't exist.
+ CanonicalServerInfoMap::const_iterator GetCanonicalServerInfoHost(
+ const quic::QuicServerId& server) const;
+
+ // Remove the canonical alt-svc host for |server|.
+ void RemoveAltSvcCanonicalHost(const url::SchemeHostPort& server);
+
+ // Update |canonical_server_info_map_| with the new canonical host.
+ // The |server| should have the corresponding server info associated with it
+ // in |quic_server_info_map_|. If |canonical_server_info_map_| doesn't
+ // have an entry associated with |server|, the method will add one.
+ void UpdateCanonicalServerInfoMap(const quic::QuicServerId& server);
+
+ // Returns the canonical host suffix for |host|, or nullptr if none
+ // exists.
+ const std::string* GetCanonicalSuffix(const std::string& host) const;
+
+ void OnPrefsLoaded(
+ std::unique_ptr<SpdyServersMap> spdy_servers_map,
+ std::unique_ptr<AlternativeServiceMap> alternative_service_map,
+ std::unique_ptr<ServerNetworkStatsMap> server_network_stats_map,
+ const IPAddress& last_quic_address,
+ std::unique_ptr<QuicServerInfoMap> quic_server_info_map,
+ std::unique_ptr<BrokenAlternativeServiceList>
+ broken_alternative_service_list,
+ std::unique_ptr<RecentlyBrokenAlternativeServices>
+ recently_broken_alternative_services,
+ bool prefs_corrupt);
+
+ // These methods are called by OnPrefsLoaded to handle merging properties
+ // loaded from prefs with what has been learned while waiting for prefs to
+ // load.
+ void OnSpdyServersLoaded(std::unique_ptr<SpdyServersMap> spdy_servers_map);
+ void OnAlternativeServiceServersLoaded(
+ std::unique_ptr<AlternativeServiceMap> alternate_protocol_servers);
+ void OnServerNetworkStatsLoaded(
+ std::unique_ptr<ServerNetworkStatsMap> server_network_stats_map);
+ void OnSupportsQuicLoaded(const IPAddress& last_address);
+ void OnQuicServerInfoMapLoaded(
+ std::unique_ptr<QuicServerInfoMap> quic_server_info_map);
+ void OnBrokenAndRecentlyBrokenAlternativeServicesLoaded(
+ std::unique_ptr<BrokenAlternativeServiceList>
+ broken_alternative_service_list,
+ std::unique_ptr<RecentlyBrokenAlternativeServices>
+ recently_broken_alternative_services);
+
+ // Queue a delayed call to WriteProperties(). If |is_initialized_| is false,
+ // or |properties_manager_| is nullptr, or there's already a queued call to
+ // WriteProperties(), does nothing.
+ void MaybeQueueWriteProperties();
+
+ // Writes cached state to |properties_manager_|, which must not be null.
+ // Invokes |callback| on completion, if non-null.
+ void WriteProperties(base::OnceClosure callback) const;
+
+ const base::TickClock* tick_clock_; // Unowned
+ base::Clock* clock_; // Unowned
+
+ // Set to true once initial properties have been retrieved from disk by
+ // |properties_manager_|. Always true if |properties_manager_| is nullptr.
+ bool is_initialized_;
+
+ // Used to load/save properties from/to preferences. May be nullptr.
+ std::unique_ptr<HttpServerPropertiesManager> properties_manager_;
+
+ SpdyServersMap spdy_servers_map_;
+ Http11ServerHostPortSet http11_servers_;
+
+ AlternativeServiceMap alternative_service_map_;
+
+ BrokenAlternativeServices broken_alternative_services_;
+
+ IPAddress last_quic_address_;
+ ServerNetworkStatsMap server_network_stats_map_;
+ // Contains a map of servers which could share the same alternate protocol.
+ // Map from a Canonical scheme/host/port (host is some postfix of host names)
+ // to an actual origin, which has a plausible alternate protocol mapping.
+ CanonicalAltSvcMap canonical_alt_svc_map_;
+
+ // Contains list of suffixes (for example ".c.youtube.com",
+ // ".googlevideo.com", ".googleusercontent.com") of canonical hostnames.
+ const CanonicalSuffixList canonical_suffixes_;
+
+ QuicServerInfoMap quic_server_info_map_;
+
+ // Maps canonical suffixes to host names that have the same canonical suffix
+ // and have a corresponding entry in |quic_server_info_map_|. The map can be
+ // used to quickly look for server info for hosts that share the same
+ // canonical suffix but don't have exact match in |quic_server_info_map_|. The
+ // map exists solely to improve the search performance. It only contains
+ // derived data that can be recalculated by traversing
+ // |quic_server_info_map_|.
+ CanonicalServerInfoMap canonical_server_info_map_;
+
+ size_t max_server_configs_stored_in_properties_;
+
+ // Used to post calls to WriteProperties().
+ base::OneShotTimer prefs_update_timer_;
+
+ THREAD_CHECKER(thread_checker_);
+
DISALLOW_COPY_AND_ASSIGN(HttpServerProperties);
};