diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2020-01-20 13:40:20 +0100 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2020-01-22 12:41:23 +0000 |
commit | 7961cea6d1041e3e454dae6a1da660b453efd238 (patch) | |
tree | c0eeb4a9ff9ba32986289c1653d9608e53ccb444 /chromium/net/http/http_server_properties_manager.cc | |
parent | b7034d0803538058e5c9d904ef03cf5eab34f6ef (diff) | |
download | qtwebengine-chromium-7961cea6d1041e3e454dae6a1da660b453efd238.tar.gz |
BASELINE: Update Chromium to 78.0.3904.130
Change-Id: If185e0c0061b3437531c97c9c8c78f239352a68b
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/net/http/http_server_properties_manager.cc')
-rw-r--r-- | chromium/net/http/http_server_properties_manager.cc | 826 |
1 files changed, 234 insertions, 592 deletions
diff --git a/chromium/net/http/http_server_properties_manager.cc b/chromium/net/http/http_server_properties_manager.cc index 8cb7cd9d563..33c8e5aebd2 100644 --- a/chromium/net/http/http_server_properties_manager.cc +++ b/chromium/net/http/http_server_properties_manager.cc @@ -7,31 +7,26 @@ #include <utility> #include "base/bind.h" +#include "base/feature_list.h" #include "base/metrics/histogram_macros.h" #include "base/stl_util.h" #include "base/strings/string_number_conversions.h" +#include "base/time/tick_clock.h" #include "base/values.h" +#include "net/base/features.h" #include "net/base/host_port_pair.h" #include "net/base/ip_address.h" #include "net/base/port_util.h" #include "net/base/privacy_mode.h" +#include "net/http/http_server_properties.h" #include "net/third_party/quiche/src/quic/platform/api/quic_hostname_utils.h" #include "url/gurl.h" +#include "url/scheme_host_port.h" namespace net { namespace { -// Time to wait before starting an update the http_server_properties_impl_ cache -// from preferences. Scheduling another update during this period will be a -// no-op. -constexpr base::TimeDelta kUpdateCacheDelay = base::TimeDelta::FromSeconds(1); - -// Time to wait before starting an update the preferences from the -// http_server_properties_impl_ cache. Scheduling another update during this -// period will be a no-op. -constexpr base::TimeDelta kUpdatePrefsDelay = base::TimeDelta::FromSeconds(60); - // "version" 0 indicates, http_server_properties doesn't have "version" // property. const int kMissingVersion = 0; @@ -42,6 +37,8 @@ const int kVersionNumber = 5; // Persist at most 200 currently-broken alternative services to disk. const int kMaxBrokenAlternativeServicesToPersist = 200; +const char kServerKey[] = "server"; +const char kNetworkIsolationKey[] = "isolation"; const char kVersionKey[] = "version"; const char kServersKey[] = "servers"; const char kSupportsSpdyKey[] = "supports_spdy"; @@ -62,6 +59,49 @@ const char kBrokenAlternativeServicesKey[] = "broken_alternative_services"; const char kBrokenUntilKey[] = "broken_until"; const char kBrokenCountKey[] = "broken_count"; +// Utility method to return only those AlternativeServiceInfos that should be +// persisted to disk. In particular, removes expired and invalid alternative +// services. Also checks if an alternative service for the same canonical suffix +// has already been saved, and if so, returns an empty list. +AlternativeServiceInfoVector GetAlternativeServiceToPersist( + const base::Optional<AlternativeServiceInfoVector>& alternative_services, + const HttpServerProperties::ServerInfoMapKey& server_info_key, + base::Time now, + const HttpServerPropertiesManager::GetCannonicalSuffix& + get_canonical_suffix, + std::set<std::pair<std::string, NetworkIsolationKey>>* + persisted_canonical_suffix_set) { + if (!alternative_services) + return AlternativeServiceInfoVector(); + // Separate out valid, non-expired AlternativeServiceInfo entries. + AlternativeServiceInfoVector notbroken_alternative_service_info_vector; + for (const auto& alternative_service_info : alternative_services.value()) { + if (alternative_service_info.expiration() < now || + !IsAlternateProtocolValid( + alternative_service_info.alternative_service().protocol)) { + continue; + } + notbroken_alternative_service_info_vector.push_back( + alternative_service_info); + } + if (notbroken_alternative_service_info_vector.empty()) + return notbroken_alternative_service_info_vector; + const std::string* canonical_suffix = + get_canonical_suffix.Run(server_info_key.server.host()); + if (canonical_suffix) { + // Don't save if have already saved information associated with the same + // canonical suffix. + std::pair<std::string, NetworkIsolationKey> index( + *canonical_suffix, server_info_key.network_isolation_key); + if (persisted_canonical_suffix_set->find(index) != + persisted_canonical_suffix_set->end()) { + return AlternativeServiceInfoVector(); + } + persisted_canonical_suffix_set->emplace(std::move(index)); + } + return notbroken_alternative_service_info_vector; +} + void AddAlternativeServiceFieldsToDictionaryValue( const AlternativeService& alternative_service, base::DictionaryValue* dict) { @@ -73,15 +113,6 @@ void AddAlternativeServiceFieldsToDictionaryValue( NextProtoToString(alternative_service.protocol)); } -// A local or temporary data structure to hold preferences for a server. -// This is used only in UpdatePrefs. -struct ServerPref { - bool supports_spdy = false; - AlternativeServiceInfoVector alternative_service_info_vector; - bool server_network_stats_valid = false; - ServerNetworkStats server_network_stats; -}; - quic::QuicServerId QuicServerIdFromString(const std::string& str) { GURL url(str); if (!url.is_valid()) { @@ -105,342 +136,46 @@ std::string QuicServerIdToString(const quic::QuicServerId& server_id) { //////////////////////////////////////////////////////////////////////////////// // HttpServerPropertiesManager -HttpServerPropertiesManager::PrefDelegate::~PrefDelegate() = default; - HttpServerPropertiesManager::HttpServerPropertiesManager( - std::unique_ptr<PrefDelegate> pref_delegate, + std::unique_ptr<HttpServerProperties::PrefDelegate> pref_delegate, + OnPrefsLoadedCallback on_prefs_loaded_callback, + size_t max_server_configs_stored_in_properties, NetLog* net_log, const base::TickClock* clock) : pref_delegate_(std::move(pref_delegate)), - clock_(clock ? clock : base::DefaultTickClock::GetInstance()), + on_prefs_loaded_callback_(std::move(on_prefs_loaded_callback)), + max_server_configs_stored_in_properties_( + max_server_configs_stored_in_properties), + clock_(clock), net_log_( NetLogWithSource::Make(net_log, NetLogSourceType::HTTP_SERVER_PROPERTIES)) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(pref_delegate_); + DCHECK(on_prefs_loaded_callback_); DCHECK(clock_); - pref_delegate_->StartListeningForUpdates(base::BindRepeating( - &HttpServerPropertiesManager::OnHttpServerPropertiesChanged, - base::Unretained(this))); + pref_delegate_->WaitForPrefLoad( + base::BindOnce(&HttpServerPropertiesManager::OnHttpServerPropertiesLoaded, + pref_load_weak_ptr_factory_.GetWeakPtr())); net_log_.BeginEvent(NetLogEventType::HTTP_SERVER_PROPERTIES_INITIALIZATION); - - http_server_properties_impl_.reset( - new HttpServerPropertiesImpl(clock_, nullptr)); } HttpServerPropertiesManager::~HttpServerPropertiesManager() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - // Flush settings on destruction. - UpdatePrefsFromCache(base::OnceClosure()); -} - -void HttpServerPropertiesManager::Clear(base::OnceClosure callback) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - - http_server_properties_impl_->Clear(base::OnceClosure()); - UpdatePrefsFromCache(std::move(callback)); -} - -bool HttpServerPropertiesManager::SupportsRequestPriority( - const url::SchemeHostPort& server) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - return http_server_properties_impl_->SupportsRequestPriority(server); -} - -bool HttpServerPropertiesManager::GetSupportsSpdy( - const url::SchemeHostPort& server) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - return http_server_properties_impl_->GetSupportsSpdy(server); -} - -void HttpServerPropertiesManager::SetSupportsSpdy( - const url::SchemeHostPort& server, - bool support_spdy) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - - bool old_support_spdy = http_server_properties_impl_->GetSupportsSpdy(server); - http_server_properties_impl_->SetSupportsSpdy(server, support_spdy); - bool new_support_spdy = http_server_properties_impl_->GetSupportsSpdy(server); - if (old_support_spdy != new_support_spdy) - ScheduleUpdatePrefs(); -} - -bool HttpServerPropertiesManager::RequiresHTTP11(const HostPortPair& server) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - return http_server_properties_impl_->RequiresHTTP11(server); -} - -void HttpServerPropertiesManager::SetHTTP11Required( - const HostPortPair& server) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - - http_server_properties_impl_->SetHTTP11Required(server); - ScheduleUpdatePrefs(); -} - -void HttpServerPropertiesManager::MaybeForceHTTP11(const HostPortPair& server, - SSLConfig* ssl_config) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - http_server_properties_impl_->MaybeForceHTTP11(server, ssl_config); -} - -AlternativeServiceInfoVector -HttpServerPropertiesManager::GetAlternativeServiceInfos( - const url::SchemeHostPort& origin) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - return http_server_properties_impl_->GetAlternativeServiceInfos(origin); -} - -bool HttpServerPropertiesManager::SetHttp2AlternativeService( - const url::SchemeHostPort& origin, - const AlternativeService& alternative_service, - base::Time expiration) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - const bool changed = http_server_properties_impl_->SetHttp2AlternativeService( - origin, alternative_service, expiration); - if (changed) { - ScheduleUpdatePrefs(); - } - return changed; -} - -bool HttpServerPropertiesManager::SetQuicAlternativeService( - const url::SchemeHostPort& origin, - const AlternativeService& alternative_service, - base::Time expiration, - const quic::ParsedQuicVersionVector& advertised_versions) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - const bool changed = http_server_properties_impl_->SetQuicAlternativeService( - origin, alternative_service, expiration, advertised_versions); - if (changed) { - ScheduleUpdatePrefs(); - } - return changed; -} - -bool HttpServerPropertiesManager::SetAlternativeServices( - const url::SchemeHostPort& origin, - const AlternativeServiceInfoVector& alternative_service_info_vector) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - const bool changed = http_server_properties_impl_->SetAlternativeServices( - origin, alternative_service_info_vector); - if (changed) { - ScheduleUpdatePrefs(); - } - return changed; -} - -void HttpServerPropertiesManager::MarkAlternativeServiceBroken( - const AlternativeService& alternative_service) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - http_server_properties_impl_->MarkAlternativeServiceBroken( - alternative_service); - ScheduleUpdatePrefs(); -} - -void HttpServerPropertiesManager:: - MarkAlternativeServiceBrokenUntilDefaultNetworkChanges( - const AlternativeService& alternative_service) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - http_server_properties_impl_ - ->MarkAlternativeServiceBrokenUntilDefaultNetworkChanges( - alternative_service); - ScheduleUpdatePrefs(); -} - -void HttpServerPropertiesManager::MarkAlternativeServiceRecentlyBroken( - const AlternativeService& alternative_service) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - http_server_properties_impl_->MarkAlternativeServiceRecentlyBroken( - alternative_service); - ScheduleUpdatePrefs(); -} - -bool HttpServerPropertiesManager::IsAlternativeServiceBroken( - const AlternativeService& alternative_service) const { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - return http_server_properties_impl_->IsAlternativeServiceBroken( - alternative_service); -} - -bool HttpServerPropertiesManager::WasAlternativeServiceRecentlyBroken( - const AlternativeService& alternative_service) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - return http_server_properties_impl_->WasAlternativeServiceRecentlyBroken( - alternative_service); -} - -void HttpServerPropertiesManager::ConfirmAlternativeService( - const AlternativeService& alternative_service) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - bool old_value = http_server_properties_impl_->IsAlternativeServiceBroken( - alternative_service); - http_server_properties_impl_->ConfirmAlternativeService(alternative_service); - bool new_value = http_server_properties_impl_->IsAlternativeServiceBroken( - alternative_service); - // For persisting, we only care about the value returned by - // IsAlternativeServiceBroken. If that value changes, then call persist. - if (old_value != new_value) - ScheduleUpdatePrefs(); -} - -bool HttpServerPropertiesManager::OnDefaultNetworkChanged() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - bool changed = http_server_properties_impl_->OnDefaultNetworkChanged(); - if (changed) - ScheduleUpdatePrefs(); - return changed; -} - -const AlternativeServiceMap& -HttpServerPropertiesManager::alternative_service_map() const { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - return http_server_properties_impl_->alternative_service_map(); -} - -std::unique_ptr<base::Value> -HttpServerPropertiesManager::GetAlternativeServiceInfoAsValue() const { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - return http_server_properties_impl_->GetAlternativeServiceInfoAsValue(); -} - -bool HttpServerPropertiesManager::GetSupportsQuic( - IPAddress* last_address) const { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - return http_server_properties_impl_->GetSupportsQuic(last_address); -} - -void HttpServerPropertiesManager::SetSupportsQuic(bool used_quic, - const IPAddress& address) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - IPAddress old_last_quic_addr; - http_server_properties_impl_->GetSupportsQuic(&old_last_quic_addr); - http_server_properties_impl_->SetSupportsQuic(used_quic, address); - IPAddress new_last_quic_addr; - http_server_properties_impl_->GetSupportsQuic(&new_last_quic_addr); - if (old_last_quic_addr != new_last_quic_addr) - ScheduleUpdatePrefs(); -} - -void HttpServerPropertiesManager::SetServerNetworkStats( - const url::SchemeHostPort& server, - ServerNetworkStats stats) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - ServerNetworkStats old_stats; - const ServerNetworkStats* old_stats_ptr = - http_server_properties_impl_->GetServerNetworkStats(server); - if (http_server_properties_impl_->GetServerNetworkStats(server)) - old_stats = *old_stats_ptr; - http_server_properties_impl_->SetServerNetworkStats(server, stats); - ServerNetworkStats new_stats = - *(http_server_properties_impl_->GetServerNetworkStats(server)); - if (old_stats != new_stats) - ScheduleUpdatePrefs(); -} - -void HttpServerPropertiesManager::ClearServerNetworkStats( - const url::SchemeHostPort& server) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - bool need_update = - http_server_properties_impl_->GetServerNetworkStats(server) != nullptr; - http_server_properties_impl_->ClearServerNetworkStats(server); - if (need_update) - ScheduleUpdatePrefs(); -} - -const ServerNetworkStats* HttpServerPropertiesManager::GetServerNetworkStats( - const url::SchemeHostPort& server) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - return http_server_properties_impl_->GetServerNetworkStats(server); -} - -const ServerNetworkStatsMap& -HttpServerPropertiesManager::server_network_stats_map() const { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - return http_server_properties_impl_->server_network_stats_map(); -} - -bool HttpServerPropertiesManager::SetQuicServerInfo( - const quic::QuicServerId& server_id, - const std::string& server_info) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - bool changed = - http_server_properties_impl_->SetQuicServerInfo(server_id, server_info); - if (changed) - ScheduleUpdatePrefs(); - return changed; -} - -const std::string* HttpServerPropertiesManager::GetQuicServerInfo( - const quic::QuicServerId& server_id) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - return http_server_properties_impl_->GetQuicServerInfo(server_id); -} - -const QuicServerInfoMap& HttpServerPropertiesManager::quic_server_info_map() - const { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - return http_server_properties_impl_->quic_server_info_map(); -} - -size_t HttpServerPropertiesManager::max_server_configs_stored_in_properties() - const { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - return http_server_properties_impl_ - ->max_server_configs_stored_in_properties(); -} - -void HttpServerPropertiesManager::SetMaxServerConfigsStoredInProperties( - size_t max_server_configs_stored_in_properties) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - return http_server_properties_impl_->SetMaxServerConfigsStoredInProperties( - max_server_configs_stored_in_properties); } -bool HttpServerPropertiesManager::IsInitialized() const { +void HttpServerPropertiesManager::ReadPrefs( + std::unique_ptr<HttpServerProperties::ServerInfoMap>* server_info_map, + 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) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - return is_initialized_; -} - -// static -base::TimeDelta HttpServerPropertiesManager::GetUpdateCacheDelayForTesting() { - return kUpdateCacheDelay; -} - -// static -base::TimeDelta HttpServerPropertiesManager::GetUpdatePrefsDelayForTesting() { - return kUpdatePrefsDelay; -} - -void HttpServerPropertiesManager::ScheduleUpdateCacheForTesting() { - ScheduleUpdateCache(); -} - -void HttpServerPropertiesManager::ScheduleUpdateCache() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - // Do not schedule a new update if there is already one scheduled. - if (pref_cache_update_timer_.IsRunning()) - return; - - if (!is_initialized_) { - UpdateCacheFromPrefs(); - return; - } - - pref_cache_update_timer_.Start( - FROM_HERE, kUpdateCacheDelay, this, - &HttpServerPropertiesManager::UpdateCacheFromPrefs); -} - -void HttpServerPropertiesManager::UpdateCacheFromPrefs() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - - if (!is_initialized_) { - net_log_.EndEvent(NetLogEventType::HTTP_SERVER_PROPERTIES_INITIALIZATION); - is_initialized_ = true; - } + net_log_.EndEvent(NetLogEventType::HTTP_SERVER_PROPERTIES_INITIALIZATION); const base::DictionaryValue* http_server_properties_dict = pref_delegate_->GetServerProperties(); @@ -448,7 +183,6 @@ void HttpServerPropertiesManager::UpdateCacheFromPrefs() { if (!http_server_properties_dict) return; - bool detected_corrupted_prefs = false; net_log_.AddEvent(NetLogEventType::HTTP_SERVER_PROPERTIES_UPDATE_CACHE, [&] { return http_server_properties_dict->Clone(); }); int version_number = kMissingVersion; @@ -460,7 +194,6 @@ void HttpServerPropertiesManager::UpdateCacheFromPrefs() { return; } - const base::DictionaryValue* servers_dict = nullptr; const base::ListValue* servers_list = nullptr; // For Version 5, data is stored in the following format. // |servers| are saved in MRU order. |servers| are in the format flattened @@ -481,54 +214,42 @@ void HttpServerPropertiesManager::UpdateCacheFromPrefs() { return; } - std::unique_ptr<IPAddress> addr = std::make_unique<IPAddress>(); - ReadSupportsQuic(*http_server_properties_dict, addr.get()); + ReadSupportsQuic(*http_server_properties_dict, last_quic_address); - // String is "scheme://host:port" tuple of spdy server. - std::unique_ptr<SpdyServersMap> spdy_servers_map = - std::make_unique<SpdyServersMap>(); - std::unique_ptr<AlternativeServiceMap> alternative_service_map = - std::make_unique<AlternativeServiceMap>(); - std::unique_ptr<ServerNetworkStatsMap> server_network_stats_map = - std::make_unique<ServerNetworkStatsMap>(); - std::unique_ptr<QuicServerInfoMap> quic_server_info_map = - std::make_unique<QuicServerInfoMap>( - max_server_configs_stored_in_properties()); + *server_info_map = std::make_unique<HttpServerProperties::ServerInfoMap>(); + *quic_server_info_map = std::make_unique<QuicServerInfoMap>( + max_server_configs_stored_in_properties_); + + bool use_network_isolation_key = base::FeatureList::IsEnabled( + features::kPartitionHttpServerPropertiesByNetworkIsolationKey); // Iterate servers list in reverse MRU order so that entries are inserted // into |spdy_servers_map|, |alternative_service_map|, and // |server_network_stats_map| from oldest to newest. + const base::DictionaryValue* server_dict = nullptr; for (auto it = servers_list->end(); it != servers_list->begin();) { --it; - if (!it->GetAsDictionary(&servers_dict)) { + if (!it->GetAsDictionary(&server_dict)) { DVLOG(1) << "Malformed http_server_properties for servers dictionary."; - detected_corrupted_prefs = true; continue; } - if (!AddServersData(*servers_dict, spdy_servers_map.get(), - alternative_service_map.get(), - server_network_stats_map.get())) { - detected_corrupted_prefs = true; - } + AddServerData(*server_dict, server_info_map->get(), + use_network_isolation_key); } - if (!AddToQuicServerInfoMap(*http_server_properties_dict, - quic_server_info_map.get())) { - detected_corrupted_prefs = true; - } + AddToQuicServerInfoMap(*http_server_properties_dict, + quic_server_info_map->get()); // Read list containing broken and recently-broken alternative services, if // it exists. - std::unique_ptr<BrokenAlternativeServiceList> broken_alternative_service_list; - std::unique_ptr<RecentlyBrokenAlternativeServices> - recently_broken_alternative_services; const base::ListValue* broken_alt_svc_list; if (http_server_properties_dict->GetListWithoutPathExpansion( kBrokenAlternativeServicesKey, &broken_alt_svc_list)) { - broken_alternative_service_list = + *broken_alternative_service_list = std::make_unique<BrokenAlternativeServiceList>(); - recently_broken_alternative_services = - std::make_unique<RecentlyBrokenAlternativeServices>(); + *recently_broken_alternative_services = + std::make_unique<RecentlyBrokenAlternativeServices>( + kMaxRecentlyBrokenAlternativeServiceEntries); // Iterate list in reverse-MRU order for (auto it = broken_alt_svc_list->end(); @@ -537,60 +258,34 @@ void HttpServerPropertiesManager::UpdateCacheFromPrefs() { const base::DictionaryValue* entry_dict; if (!it->GetAsDictionary(&entry_dict)) { DVLOG(1) << "Malformed broken alterantive service entry."; - detected_corrupted_prefs = true; - continue; - } - if (!AddToBrokenAlternativeServices( - *entry_dict, broken_alternative_service_list.get(), - recently_broken_alternative_services.get())) { - detected_corrupted_prefs = true; continue; } + AddToBrokenAlternativeServices( + *entry_dict, broken_alternative_service_list->get(), + recently_broken_alternative_services->get()); } } // Set the properties loaded from prefs on |http_server_properties_impl_|. - UMA_HISTOGRAM_COUNTS_1M("Net.CountOfSpdyServers", spdy_servers_map->size()); - http_server_properties_impl_->SetSpdyServers(std::move(spdy_servers_map)); - - // Update the cached data and use the new alternative service list from - // preferences. - UMA_HISTOGRAM_COUNTS_1M("Net.CountOfAlternateProtocolServers", - alternative_service_map->size()); - http_server_properties_impl_->SetAlternativeServiceServers( - std::move(alternative_service_map)); - - http_server_properties_impl_->SetSupportsQuic(*addr); - - http_server_properties_impl_->SetServerNetworkStats( - std::move(server_network_stats_map)); + // TODO(mmenke): Rename this once more information is stored in this map. + UMA_HISTOGRAM_COUNTS_1M("Net.HttpServerProperties.CountOfServers", + (*server_info_map)->size()); UMA_HISTOGRAM_COUNTS_1000("Net.CountOfQuicServerInfos", - quic_server_info_map->size()); - - http_server_properties_impl_->SetQuicServerInfoMap( - std::move(quic_server_info_map)); + (*quic_server_info_map)->size()); - if (recently_broken_alternative_services) { - DCHECK(broken_alternative_service_list); + if (*recently_broken_alternative_services) { + DCHECK(*broken_alternative_service_list); UMA_HISTOGRAM_COUNTS_1000("Net.CountOfBrokenAlternativeServices", - broken_alternative_service_list->size()); + (*broken_alternative_service_list)->size()); UMA_HISTOGRAM_COUNTS_1000("Net.CountOfRecentlyBrokenAlternativeServices", - recently_broken_alternative_services->size()); - - http_server_properties_impl_->SetBrokenAndRecentlyBrokenAlternativeServices( - std::move(broken_alternative_service_list), - std::move(recently_broken_alternative_services)); + (*recently_broken_alternative_services)->size()); } - - // Update the prefs with what we have read (delete all corrupted prefs). - if (detected_corrupted_prefs) - ScheduleUpdatePrefs(); } -bool HttpServerPropertiesManager::AddToBrokenAlternativeServices( +void HttpServerPropertiesManager::AddToBrokenAlternativeServices( const base::DictionaryValue& broken_alt_svc_entry_dict, BrokenAlternativeServiceList* broken_alternative_service_list, RecentlyBrokenAlternativeServices* recently_broken_alternative_services) { @@ -598,7 +293,7 @@ bool HttpServerPropertiesManager::AddToBrokenAlternativeServices( if (!ParseAlternativeServiceDict(broken_alt_svc_entry_dict, false, "broken alternative services", &alt_service)) { - return false; + return; } // Each entry must contain either broken-count and/or broken-until fields. @@ -612,11 +307,11 @@ bool HttpServerPropertiesManager::AddToBrokenAlternativeServices( kBrokenCountKey, &broken_count)) { DVLOG(1) << "Recently broken alternative service has malformed " << "broken-count."; - return false; + return; } if (broken_count < 0) { DVLOG(1) << "Broken alternative service has negative broken-count."; - return false; + return; } recently_broken_alternative_services->Put(alt_service, broken_count); contains_broken_count_or_broken_until = true; @@ -632,7 +327,7 @@ bool HttpServerPropertiesManager::AddToBrokenAlternativeServices( !base::StringToInt64(expiration_string, &expiration_int64)) { DVLOG(1) << "Broken alternative service has malformed broken-until " << "string."; - return false; + return; } time_t expiration_time_t = static_cast<time_t>(expiration_int64); @@ -648,49 +343,50 @@ bool HttpServerPropertiesManager::AddToBrokenAlternativeServices( if (!contains_broken_count_or_broken_until) { DVLOG(1) << "Broken alternative service has neither broken-count nor " << "broken-until specified."; - return false; } - - return true; } -bool HttpServerPropertiesManager::AddServersData( - const base::DictionaryValue& servers_dict, - SpdyServersMap* spdy_servers_map, - AlternativeServiceMap* alternative_service_map, - ServerNetworkStatsMap* network_stats_map) { - for (base::DictionaryValue::Iterator it(servers_dict); !it.IsAtEnd(); - it.Advance()) { - // Get server's scheme/host/pair. - const std::string& server_str = it.key(); - std::string spdy_server_url = server_str; - url::SchemeHostPort spdy_server((GURL(spdy_server_url))); - if (spdy_server.host().empty()) { - DVLOG(1) << "Malformed http_server_properties for server: " << server_str; - return false; - } +void HttpServerPropertiesManager::AddServerData( + const base::DictionaryValue& server_dict, + HttpServerProperties::ServerInfoMap* server_info_map, + bool use_network_isolation_key) { + // Get server's scheme/host/pair. + const std::string* server_str = server_dict.FindStringKey(kServerKey); + const base::Value* network_isolation_key_value = + server_dict.FindKey(kNetworkIsolationKey); + NetworkIsolationKey network_isolation_key; + // Can't load entry if server name missing, or if the network isolation key is + // missing or invalid. + if (!server_str || !network_isolation_key_value || + !NetworkIsolationKey::FromValue(*network_isolation_key_value, + &network_isolation_key)) { + return; + } - const base::DictionaryValue* server_pref_dict = nullptr; - if (!it.value().GetAsDictionary(&server_pref_dict)) { - DVLOG(1) << "Malformed http_server_properties server: " << server_str; - return false; - } + // If the entry includes a non-empty NetworkIsolationKey, but using a network + // isolation key is currently disabled, throw away the entry. + if (!network_isolation_key.IsEmpty() && !use_network_isolation_key) + return; - // Get if server supports Spdy. - bool supports_spdy = false; - if (server_pref_dict->GetBoolean(kSupportsSpdyKey, &supports_spdy) && - supports_spdy) { - spdy_servers_map->Put(spdy_server.Serialize(), supports_spdy); - } + url::SchemeHostPort spdy_server((GURL(*server_str))); + if (spdy_server.host().empty()) { + DVLOG(1) << "Malformed http_server_properties for server: " << server_str; + return; + } - if (!AddToAlternativeServiceMap(spdy_server, *server_pref_dict, - alternative_service_map) || - !AddToNetworkStatsMap(spdy_server, *server_pref_dict, - network_stats_map)) { - return false; - } + HttpServerProperties::ServerInfo server_info; + + server_info.supports_spdy = server_dict.FindBoolKey(kSupportsSpdyKey); + + if (ParseAlternativeServiceInfo(spdy_server, server_dict, &server_info)) + ParseNetworkStats(spdy_server, server_dict, &server_info); + + if (!server_info.empty()) { + server_info_map->Put( + HttpServerProperties::ServerInfoMapKey( + spdy_server, network_isolation_key, use_network_isolation_key), + std::move(server_info)); } - return true; } bool HttpServerPropertiesManager::ParseAlternativeServiceDict( @@ -801,12 +497,11 @@ bool HttpServerPropertiesManager::ParseAlternativeServiceInfoDictOfServer( return true; } -bool HttpServerPropertiesManager::AddToAlternativeServiceMap( +bool HttpServerPropertiesManager::ParseAlternativeServiceInfo( const url::SchemeHostPort& server, const base::DictionaryValue& server_pref_dict, - AlternativeServiceMap* alternative_service_map) { - DCHECK(alternative_service_map->Peek(server) == - alternative_service_map->end()); + HttpServerProperties::ServerInfo* server_info) { + DCHECK(!server_info->alternative_services.has_value()); const base::ListValue* alternative_service_list; if (!server_pref_dict.GetListWithoutPathExpansion( kAlternativeServiceKey, &alternative_service_list)) { @@ -837,73 +532,69 @@ bool HttpServerPropertiesManager::AddToAlternativeServiceMap( return false; } - alternative_service_map->Put(server, alternative_service_info_vector); + server_info->alternative_services = alternative_service_info_vector; return true; } -bool HttpServerPropertiesManager::ReadSupportsQuic( +void HttpServerPropertiesManager::ReadSupportsQuic( const base::DictionaryValue& http_server_properties_dict, IPAddress* last_quic_address) { const base::DictionaryValue* supports_quic_dict = nullptr; if (!http_server_properties_dict.GetDictionaryWithoutPathExpansion( kSupportsQuicKey, &supports_quic_dict)) { - return true; + return; } bool used_quic = false; if (!supports_quic_dict->GetBooleanWithoutPathExpansion(kUsedQuicKey, &used_quic)) { DVLOG(1) << "Malformed SupportsQuic"; - return false; + return; } if (!used_quic) - return false; + return; std::string address; if (!supports_quic_dict->GetStringWithoutPathExpansion(kAddressKey, &address) || !last_quic_address->AssignFromIPLiteral(address)) { DVLOG(1) << "Malformed SupportsQuic"; - return false; } - return true; } -bool HttpServerPropertiesManager::AddToNetworkStatsMap( +void HttpServerPropertiesManager::ParseNetworkStats( const url::SchemeHostPort& server, const base::DictionaryValue& server_pref_dict, - ServerNetworkStatsMap* network_stats_map) { - DCHECK(network_stats_map->Peek(server) == network_stats_map->end()); + HttpServerProperties::ServerInfo* server_info) { + DCHECK(!server_info->server_network_stats.has_value()); const base::DictionaryValue* server_network_stats_dict = nullptr; if (!server_pref_dict.GetDictionaryWithoutPathExpansion( kNetworkStatsKey, &server_network_stats_dict)) { - return true; + return; } int srtt; if (!server_network_stats_dict->GetIntegerWithoutPathExpansion(kSrttKey, &srtt)) { DVLOG(1) << "Malformed ServerNetworkStats for server: " << server.Serialize(); - return false; + return; } ServerNetworkStats server_network_stats; server_network_stats.srtt = base::TimeDelta::FromMicroseconds(srtt); // TODO(rtenneti): When QUIC starts using bandwidth_estimate, then persist // bandwidth_estimate. - network_stats_map->Put(server, server_network_stats); - return true; + server_info->server_network_stats = server_network_stats; } -bool HttpServerPropertiesManager::AddToQuicServerInfoMap( +void HttpServerPropertiesManager::AddToQuicServerInfoMap( const base::DictionaryValue& http_server_properties_dict, QuicServerInfoMap* quic_server_info_map) { const base::DictionaryValue* quic_servers_dict = nullptr; if (!http_server_properties_dict.GetDictionaryWithoutPathExpansion( kQuicServers, &quic_servers_dict)) { DVLOG(1) << "Malformed http_server_properties for quic_servers."; - return true; + return; } - bool detected_corrupted_prefs = false; for (base::DictionaryValue::Iterator it(*quic_servers_dict); !it.IsAtEnd(); it.Advance()) { // Get quic_server_id. @@ -914,7 +605,6 @@ bool HttpServerPropertiesManager::AddToQuicServerInfoMap( if (quic_server_id.host().empty()) { DVLOG(1) << "Malformed http_server_properties for quic server: " << quic_server_id_str; - detected_corrupted_prefs = true; continue; } @@ -922,7 +612,6 @@ bool HttpServerPropertiesManager::AddToQuicServerInfoMap( if (!it.value().GetAsDictionary(&quic_server_pref_dict)) { DVLOG(1) << "Malformed http_server_properties quic server dict: " << quic_server_id_str; - detected_corrupted_prefs = true; continue; } @@ -931,156 +620,90 @@ bool HttpServerPropertiesManager::AddToQuicServerInfoMap( kServerInfoKey, &quic_server_info)) { DVLOG(1) << "Malformed http_server_properties quic server info: " << quic_server_id_str; - detected_corrupted_prefs = true; continue; } quic_server_info_map->Put(quic_server_id, quic_server_info); } - return !detected_corrupted_prefs; } -void HttpServerPropertiesManager::ScheduleUpdatePrefs() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - // Do not schedule a new update if there is already one scheduled. - if (network_prefs_update_timer_.IsRunning()) - return; - - network_prefs_update_timer_.Start( - FROM_HERE, kUpdatePrefsDelay, - base::Bind(&HttpServerPropertiesManager::UpdatePrefsFromCache, - base::Unretained(this), base::Passed(base::OnceClosure()))); -} - -void HttpServerPropertiesManager::UpdatePrefsFromCache( +void HttpServerPropertiesManager::WriteToPrefs( + const HttpServerProperties::ServerInfoMap& server_info_map, + const GetCannonicalSuffix& get_canonical_suffix, + const IPAddress& last_quic_address, + const QuicServerInfoMap& quic_server_info_map, + const BrokenAlternativeServiceList& broken_alternative_service_list, + const RecentlyBrokenAlternativeServices& + recently_broken_alternative_services, base::OnceClosure callback) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - typedef base::MRUCache<url::SchemeHostPort, ServerPref> ServerPrefMap; - ServerPrefMap server_pref_map(ServerPrefMap::NO_AUTO_EVICT); - - // Add SPDY servers to |server_pref_map|. - const SpdyServersMap& spdy_servers_map = - http_server_properties_impl_->spdy_servers_map(); - for (auto it = spdy_servers_map.rbegin(); it != spdy_servers_map.rend(); - ++it) { - // Only add servers that support SPDY. - if (!it->second) - continue; - - url::SchemeHostPort server(GURL(it->first)); - auto map_it = server_pref_map.Put(server, ServerPref()); - map_it->second.supports_spdy = true; - } + // If loading prefs hasn't completed, don't call it, since this will overwrite + // existing prefs. + on_prefs_loaded_callback_.Reset(); - // Add alternative service info to |server_pref_map|. - const AlternativeServiceMap& alternative_service_map = - http_server_properties_impl_->alternative_service_map(); - UMA_HISTOGRAM_COUNTS_1M("Net.CountOfAlternateProtocolServers.Memory", - alternative_service_map.size()); - typedef std::map<std::string, bool> CanonicalHostPersistedMap; - CanonicalHostPersistedMap persisted_map; + std::set<std::pair<std::string, NetworkIsolationKey>> + persisted_canonical_suffix_set; const base::Time now = base::Time::Now(); - for (auto it = alternative_service_map.rbegin(); - it != alternative_service_map.rend(); ++it) { - const url::SchemeHostPort& server = it->first; - AlternativeServiceInfoVector notbroken_alternative_service_info_vector; - for (const AlternativeServiceInfo& alternative_service_info : it->second) { - // Do not persist expired entries - if (alternative_service_info.expiration() < now) { - continue; - } - if (!IsAlternateProtocolValid( - alternative_service_info.alternative_service().protocol)) { - continue; - } - notbroken_alternative_service_info_vector.push_back( - alternative_service_info); - } - if (notbroken_alternative_service_info_vector.empty()) { - continue; - } - const std::string* canonical_suffix = - http_server_properties_impl_->GetCanonicalSuffix(server.host()); - if (canonical_suffix != nullptr) { - if (persisted_map.find(*canonical_suffix) != persisted_map.end()) - continue; - persisted_map[*canonical_suffix] = true; - } - - auto map_it = server_pref_map.Get(server); - if (map_it == server_pref_map.end()) - map_it = server_pref_map.Put(server, ServerPref()); - map_it->second.alternative_service_info_vector = - std::move(notbroken_alternative_service_info_vector); - } - - // Add server network stats to |server_pref_map|. - const ServerNetworkStatsMap& server_network_stats_map = - http_server_properties_impl_->server_network_stats_map(); - for (auto it = server_network_stats_map.rbegin(); - it != server_network_stats_map.rend(); ++it) { - const url::SchemeHostPort& server = it->first; - auto map_it = server_pref_map.Get(server); - if (map_it == server_pref_map.end()) - map_it = server_pref_map.Put(server, ServerPref()); - map_it->second.server_network_stats_valid = true; - map_it->second.server_network_stats = it->second; - } - base::DictionaryValue http_server_properties_dict; - // Convert |server_pref_map| to a DictionaryValue and add it to + // Convert |server_info_map| to a DictionaryValue and add it to // |http_server_properties_dict|. - auto servers_list = std::make_unique<base::ListValue>(); - for (ServerPrefMap::const_reverse_iterator map_it = server_pref_map.rbegin(); - map_it != server_pref_map.rend(); ++map_it) { - const url::SchemeHostPort server = map_it->first; - const ServerPref& server_pref = map_it->second; + base::Value servers_list(base::Value::Type::LIST); + for (auto map_it = server_info_map.rbegin(); map_it != server_info_map.rend(); + ++map_it) { + const HttpServerProperties::ServerInfoMapKey key = map_it->first; + const HttpServerProperties::ServerInfo& server_info = map_it->second; + + // If can't convert the NetworkIsolationKey to a value, don't save to disk. + // Generally happens because the key is for a unique origin. + base::Value network_isolation_key_value; + if (!key.network_isolation_key.ToValue(&network_isolation_key_value)) + continue; - auto servers_dict = std::make_unique<base::DictionaryValue>(); - auto server_pref_dict = std::make_unique<base::DictionaryValue>(); + base::DictionaryValue server_dict; - if (server_pref.supports_spdy) { - server_pref_dict->SetBoolean(kSupportsSpdyKey, server_pref.supports_spdy); - } - if (!server_pref.alternative_service_info_vector.empty()) { - SaveAlternativeServiceToServerPrefs( - server_pref.alternative_service_info_vector, server_pref_dict.get()); - } - if (server_pref.server_network_stats_valid) { - SaveNetworkStatsToServerPrefs(server_pref.server_network_stats, - server_pref_dict.get()); + bool supports_spdy = server_info.supports_spdy.value_or(false); + if (supports_spdy) + server_dict.SetBoolKey(kSupportsSpdyKey, supports_spdy); + + AlternativeServiceInfoVector alternative_services = + GetAlternativeServiceToPersist(server_info.alternative_services, key, + now, get_canonical_suffix, + &persisted_canonical_suffix_set); + if (!alternative_services.empty()) + SaveAlternativeServiceToServerPrefs(alternative_services, &server_dict); + + if (server_info.server_network_stats) { + SaveNetworkStatsToServerPrefs(*server_info.server_network_stats, + &server_dict); } - servers_dict->SetWithoutPathExpansion(server.Serialize(), - std::move(server_pref_dict)); - bool value = servers_list->AppendIfNotPresent(std::move(servers_dict)); - DCHECK(value); // Should never happen. + // Don't add empty entries. This can happen if, for example, all alternative + // services are empty, or |supports_spdy| is set to false, and all other + // fields are not set. + if (server_dict.DictEmpty()) + continue; + server_dict.SetStringKey(kServerKey, key.server.Serialize()); + server_dict.SetKey(kNetworkIsolationKey, + std::move(network_isolation_key_value)); + servers_list.GetList().emplace_back(std::move(server_dict)); } - http_server_properties_dict.SetWithoutPathExpansion(kServersKey, - std::move(servers_list)); + http_server_properties_dict.SetKey(kServersKey, std::move(servers_list)); http_server_properties_dict.SetInteger(kVersionKey, kVersionNumber); - IPAddress last_quic_addr; - if (http_server_properties_impl_->GetSupportsQuic(&last_quic_addr)) { - SaveSupportsQuicToPrefs(last_quic_addr, &http_server_properties_dict); - } + if (last_quic_address.IsValid()) + SaveSupportsQuicToPrefs(last_quic_address, &http_server_properties_dict); - SaveQuicServerInfoMapToServerPrefs( - http_server_properties_impl_->quic_server_info_map(), - &http_server_properties_dict); + SaveQuicServerInfoMapToServerPrefs(quic_server_info_map, + &http_server_properties_dict); SaveBrokenAlternativeServicesToPrefs( - http_server_properties_impl_->broken_alternative_service_list(), - kMaxBrokenAlternativeServicesToPersist, - http_server_properties_impl_->recently_broken_alternative_services(), - &http_server_properties_dict); + broken_alternative_service_list, kMaxBrokenAlternativeServicesToPersist, + recently_broken_alternative_services, &http_server_properties_dict); - setting_prefs_ = true; pref_delegate_->SetServerProperties(http_server_properties_dict, std::move(callback)); - setting_prefs_ = false; net_log_.AddEvent(NetLogEventType::HTTP_SERVER_PROPERTIES_UPDATE_PREFS, [&] { return http_server_properties_dict.Clone(); }); @@ -1240,10 +863,29 @@ void HttpServerPropertiesManager::SaveBrokenAlternativeServicesToPrefs( kBrokenAlternativeServicesKey, std::move(json_list)); } -void HttpServerPropertiesManager::OnHttpServerPropertiesChanged() { +void HttpServerPropertiesManager::OnHttpServerPropertiesLoaded() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (!setting_prefs_) - ScheduleUpdateCache(); + + // If prefs have already been written, nothing to do. + if (!on_prefs_loaded_callback_) + return; + + std::unique_ptr<HttpServerProperties::ServerInfoMap> server_info_map; + 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; + + ReadPrefs(&server_info_map, &last_quic_address, &quic_server_info_map, + &broken_alternative_service_list, + &recently_broken_alternative_services); + + std::move(on_prefs_loaded_callback_) + .Run(std::move(server_info_map), last_quic_address, + std::move(quic_server_info_map), + std::move(broken_alternative_service_list), + std::move(recently_broken_alternative_services)); } } // namespace net |