// Copyright 2014 The Chromium Authors // 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_MANAGER_H_ #define NET_HTTP_HTTP_SERVER_PROPERTIES_MANAGER_H_ #include #include #include "base/functional/callback.h" #include "base/gtest_prod_util.h" #include "base/memory/raw_ptr.h" #include "base/memory/weak_ptr.h" #include "base/sequence_checker.h" #include "net/base/host_port_pair.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/log/net_log_with_source.h" namespace base { class TickClock; } namespace net { class IPAddress; //////////////////////////////////////////////////////////////////////////////// // HttpServerPropertiesManager // Class responsible for serializing/deserializing HttpServerProperties and // reading from/writing to preferences. class NET_EXPORT_PRIVATE HttpServerPropertiesManager { public: // Called when prefs are loaded. If prefs completely failed to load, // everything will be nullptr. Otherwise, everything will be populated, except // |broken_alternative_service_list| and // |recently_broken_alternative_services|, which may be null. using OnPrefsLoadedCallback = base::OnceCallback server_info_map, const IPAddress& last_local_address_when_quic_worked, std::unique_ptr quic_server_info_map, std::unique_ptr broken_alternative_service_list, std::unique_ptr recently_broken_alternative_services)>; using GetCannonicalSuffix = base::RepeatingCallback; // Create an instance of the HttpServerPropertiesManager. // // |on_prefs_loaded_callback| will be invoked with values loaded from // |prefs_delegate| once prefs have been loaded from disk. // If WriteToPrefs() is invoked before this happens, // |on_prefs_loaded_callback| will never be invoked, since the written prefs // take precedence over the ones previously stored on disk. // // |clock| is used for setting expiration times and scheduling the // expiration of broken alternative services, and must not be nullptr. HttpServerPropertiesManager( std::unique_ptr pref_delegate, OnPrefsLoadedCallback on_prefs_loaded_callback, size_t max_server_configs_stored_in_properties, NetLog* net_log, const base::TickClock* clock = nullptr); HttpServerPropertiesManager(const HttpServerPropertiesManager&) = delete; HttpServerPropertiesManager& operator=(const HttpServerPropertiesManager&) = delete; ~HttpServerPropertiesManager(); // Populates passed in objects with data from preferences. If pref data is not // present, leaves all values alone. Otherwise, populates them all, with the // possible exception of the two broken alt services lists. // // Corrupted data is ignored. // // TODO(mmenke): Consider always populating fields, unconditionally, for a // simpler API. void ReadPrefs( std::unique_ptr* server_info_map, IPAddress* last_local_address_when_quic_worked, std::unique_ptr* quic_server_info_map, std::unique_ptr* broken_alternative_service_list, std::unique_ptr* recently_broken_alternative_services); void set_max_server_configs_stored_in_properties( size_t max_server_configs_stored_in_properties) { max_server_configs_stored_in_properties_ = max_server_configs_stored_in_properties; } // Update preferences with caller-provided data. Invokes |callback| when // changes have been committed, if non-null. // // If the OnPrefLoadCallback() passed to the constructor hasn't been invoked // by the time this method is called, calling this will prevent it from ever // being invoked, as this method will overwrite any previous preferences. // // Entries associated with NetworkAnonymizationKeys for opaque origins are not // written to disk. void WriteToPrefs( const HttpServerProperties::ServerInfoMap& server_info_map, const GetCannonicalSuffix& get_canonical_suffix, const IPAddress& last_local_address_when_quic_worked, const HttpServerProperties::QuicServerInfoMap& quic_server_info_map, const BrokenAlternativeServiceList& broken_alternative_service_list, const RecentlyBrokenAlternativeServices& recently_broken_alternative_services, base::OnceClosure callback); private: // TODO(mmenke): Remove these friend methods, and make all methods static that // can be. FRIEND_TEST_ALL_PREFIXES(HttpServerPropertiesManagerTest, ParseAlternativeServiceInfo); FRIEND_TEST_ALL_PREFIXES(HttpServerPropertiesManagerTest, ReadAdvertisedVersionsFromPref); FRIEND_TEST_ALL_PREFIXES(HttpServerPropertiesManagerTest, DoNotLoadAltSvcForInsecureOrigins); FRIEND_TEST_ALL_PREFIXES(HttpServerPropertiesManagerTest, DoNotLoadExpiredAlternativeService); FRIEND_TEST_ALL_PREFIXES(HttpServerPropertiesManagerTest, AdvertisedVersionsRoundTrip); void AddServerData(const base::Value::Dict& server_dict, HttpServerProperties::ServerInfoMap* server_info_map, bool use_network_anonymization_key); // Helper method used for parsing an alternative service from JSON. // |dict| is the JSON dictionary to be parsed. It should contain fields // corresponding to members of AlternativeService. // |host_optional| determines whether or not the "host" field is optional. If // optional, the default value is empty string. // |parsing_under| is used only for debug log outputs in case of error; it // should describe what section of the JSON prefs is currently being parsed. // |alternative_service| is the output of parsing |dict|. // Return value is true if parsing is successful. static bool ParseAlternativeServiceDict( const base::Value::Dict& dict, bool host_optional, const std::string& parsing_under, AlternativeService* alternative_service); static bool ParseAlternativeServiceInfoDictOfServer( const base::Value::Dict& dict, const std::string& server_str, AlternativeServiceInfo* alternative_service_info); // Attempts to populate |server_info|'s |alternative_service_info| field from // |server_dict|. Returns true if the data was no corrupted (Lack of data is // not considered corruption). static bool ParseAlternativeServiceInfo( const url::SchemeHostPort& server, const base::Value::Dict& server_dict, HttpServerProperties::ServerInfo* server_info); void ReadLastLocalAddressWhenQuicWorked( const base::Value::Dict& server_dict, IPAddress* last_local_address_when_quic_worked); void ParseNetworkStats(const url::SchemeHostPort& server, const base::Value::Dict& server_dict, HttpServerProperties::ServerInfo* server_info); void AddToQuicServerInfoMap( const base::Value::Dict& server_dict, bool use_network_anonymization_key, HttpServerProperties::QuicServerInfoMap* quic_server_info_map); void AddToBrokenAlternativeServices( const base::Value::Dict& broken_alt_svc_entry_dict, bool use_network_anonymization_key, BrokenAlternativeServiceList* broken_alternative_service_list, RecentlyBrokenAlternativeServices* recently_broken_alternative_services); void SaveAlternativeServiceToServerPrefs( const AlternativeServiceInfoVector& alternative_service_info_vector, base::Value::Dict& server_pref_dict); void SaveLastLocalAddressWhenQuicWorkedToPrefs( const IPAddress& last_local_address_when_quic_worked, base::Value::Dict& http_server_properties_dict); void SaveNetworkStatsToServerPrefs( const ServerNetworkStats& server_network_stats, base::Value::Dict& server_pref_dict); void SaveQuicServerInfoMapToServerPrefs( const HttpServerProperties::QuicServerInfoMap& quic_server_info_map, base::Value::Dict& http_server_properties_dict); void SaveBrokenAlternativeServicesToPrefs( const BrokenAlternativeServiceList& broken_alternative_service_list, size_t max_broken_alternative_services, const RecentlyBrokenAlternativeServices& recently_broken_alternative_services, base::Value::Dict& http_server_properties_dict); void OnHttpServerPropertiesLoaded(); std::unique_ptr pref_delegate_; OnPrefsLoadedCallback on_prefs_loaded_callback_; size_t max_server_configs_stored_in_properties_; raw_ptr clock_; // Unowned const NetLogWithSource net_log_; SEQUENCE_CHECKER(sequence_checker_); base::WeakPtrFactory pref_load_weak_ptr_factory_{ this}; }; } // namespace net #endif // NET_HTTP_HTTP_SERVER_PROPERTIES_MANAGER_H_