Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(267)

Unified Diff: net/http/http_server_properties_manager.cc

Issue 2932953002: Persist broken and recently-broken alt-svcs to prefs in HttpServerPropertiesManager (Closed)
Patch Set: Added a DCHECK Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: net/http/http_server_properties_manager.cc
diff --git a/net/http/http_server_properties_manager.cc b/net/http/http_server_properties_manager.cc
index 95ef2f444496beced2a3b87578b9781792a0ca76..bcab74c1e3dc0bff3c40a3ba2203eaab6576fea9 100644
--- a/net/http/http_server_properties_manager.cc
+++ b/net/http/http_server_properties_manager.cc
@@ -49,6 +49,12 @@ const int kMaxSupportsSpdyServerHostsToPersist = 300;
// Persist 200 ServerNetworkStats.
const int kMaxServerNetworkStatsHostsToPersist = 200;
+// Persist 200 BrokenAlternativeServices
+const int kMaxBrokenAlternativeServicesToPersist = 200;
+
+// Persist 200 RecentlyBrokenAlternativeServices
+const int kMaxRecentlyBrokenAlternativeServicesToPersist = 200;
+
const char kVersionKey[] = "version";
const char kServersKey[] = "servers";
const char kSupportsSpdyKey[] = "supports_spdy";
@@ -64,6 +70,9 @@ const char kPortKey[] = "port";
const char kExpirationKey[] = "expiration";
const char kNetworkStatsKey[] = "network_stats";
const char kSrttKey[] = "srtt";
+const char kBrokenAlternativeServicesKey[] = "broken_alternative_services";
+const char kRecentlyBrokenAlternativeServicesKey[] =
+ "recently_broken_alternative_services";
} // namespace
@@ -79,6 +88,7 @@ HttpServerPropertiesManager::HttpServerPropertiesManager(
: pref_task_runner_(std::move(pref_task_runner)),
pref_delegate_(pref_delegate),
setting_prefs_(false),
+ clock_(&default_clock_),
is_initialized_(false),
network_task_runner_(std::move(network_task_runner)) {
DCHECK(pref_task_runner_->RunsTasksInCurrentSequence());
@@ -514,6 +524,64 @@ void HttpServerPropertiesManager::UpdateCacheFromPrefsOnPrefSequence() {
detected_corrupted_prefs = true;
}
+ std::unique_ptr<RecentlyBrokenAlternativeServices>
+ recently_broken_alternative_services;
+ const base::ListValue* recently_broken_alt_svc_list = nullptr;
+
+ std::unique_ptr<BrokenAlternativeServiceList> broken_alternative_service_list;
+ const base::ListValue* broken_alt_svc_list = nullptr;
+
+ // Read recently broken alternative services if they exist.
+ if (http_server_properties_dict.GetListWithoutPathExpansion(
+ kRecentlyBrokenAlternativeServicesKey,
+ &recently_broken_alt_svc_list)) {
+ recently_broken_alternative_services.reset(
+ new RecentlyBrokenAlternativeServices(
+ RecentlyBrokenAlternativeServices::NO_AUTO_EVICT));
+
+ for (auto it = recently_broken_alt_svc_list->begin();
+ it != recently_broken_alt_svc_list->end(); ++it) {
+ const base::DictionaryValue* entry_dict = nullptr;
+ if (!it->GetAsDictionary(&entry_dict) ||
+ !AddRecentlyBrokenAlternativeServiceData(
+ entry_dict, recently_broken_alternative_services.get())) {
+ DVLOG(1) << "Malformed http_server_properties for recently broken "
+ << "alternative services list.";
+ detected_corrupted_prefs = true;
+ }
+ }
+
+ // Read broken alternative services if they exist
+ if (http_server_properties_dict.GetListWithoutPathExpansion(
+ kBrokenAlternativeServicesKey, &broken_alt_svc_list)) {
+ broken_alternative_service_list.reset(new BrokenAlternativeServiceList());
+
+ for (auto it = broken_alt_svc_list->begin();
+ it != broken_alt_svc_list->end(); ++it) {
+ const base::DictionaryValue* entry_dict = nullptr;
+ AlternativeService alternative_service;
+ base::TimeTicks expiration_time_ticks;
+ if (!it->GetAsDictionary(&entry_dict) ||
+ !ExtractBrokenAlternativeServiceData(
+ entry_dict, &alternative_service, &expiration_time_ticks)) {
+ DVLOG(1) << "Malformed http_server_properties for broken alternative "
+ << "services list.";
+ detected_corrupted_prefs = true;
+ continue;
+ }
+ if (recently_broken_alternative_services->Peek(alternative_service) !=
+ recently_broken_alternative_services->end()) {
+ broken_alternative_service_list->push_back(
+ std::make_pair(alternative_service, expiration_time_ticks));
+ } else {
+ DVLOG(1) << "Broken alternative service does not have an entry in "
+ << "map of recently broken alternative services. "
+ << "Will not be added.";
+ }
+ }
+ }
+ }
+
network_task_runner_->PostTask(
FROM_HERE,
base::Bind(
@@ -522,9 +590,65 @@ void HttpServerPropertiesManager::UpdateCacheFromPrefsOnPrefSequence() {
base::Owned(alternative_service_map.release()), base::Owned(addr),
base::Owned(server_network_stats_map.release()),
base::Owned(quic_server_info_map.release()),
+ base::Passed(&broken_alternative_service_list),
+ base::Passed(&recently_broken_alternative_services),
detected_corrupted_prefs));
}
+bool HttpServerPropertiesManager::ExtractBrokenAlternativeServiceData(
+ const base::DictionaryValue* broken_alternative_service_dict,
+ AlternativeService* alternative_service,
+ base::TimeTicks* expiration_time_ticks) {
+ DCHECK(broken_alternative_service_dict);
+
+ if (broken_alternative_service_dict->size() != 1u)
+ return false;
+
+ base::DictionaryValue::Iterator it(*broken_alternative_service_dict);
+
+ const std::string& alternative_service_string = it.key();
+ if (!AlternativeService::FromString(alternative_service_string,
+ alternative_service))
+ return false;
+
+ int64_t expiration_int64;
+ std::string time_ticks_string;
+ if (!it.value().GetAsString(&time_ticks_string))
+ return false;
+ if (!base::StringToInt64(time_ticks_string, &expiration_int64))
+ return false;
+ time_t expiration_time_t = static_cast<time_t>(expiration_int64);
+ // Convert expiration from time_t to Time to TimeTicks
+ *expiration_time_ticks =
+ clock_->NowTicks() +
+ (base::Time::FromTimeT(expiration_time_t) - base::Time::Now());
+
+ return true;
+}
+
+bool HttpServerPropertiesManager::AddRecentlyBrokenAlternativeServiceData(
+ const base::DictionaryValue* recently_broken_alternative_service_dict,
+ RecentlyBrokenAlternativeServices* recently_broken_alternative_services) {
+ DCHECK(recently_broken_alternative_service_dict);
+
+ if (recently_broken_alternative_service_dict->size() != 1u)
+ return false;
+
+ base::DictionaryValue::Iterator it(*recently_broken_alternative_service_dict);
+
+ AlternativeService alt_service;
+ const std::string& alt_service_string = it.key();
+ if (!AlternativeService::FromString(alt_service_string, &alt_service))
+ return false;
+
+ int broken_count;
+ if (!it.value().GetAsInteger(&broken_count))
+ return false;
+
+ recently_broken_alternative_services->Put(alt_service, broken_count);
+ return true;
+}
+
bool HttpServerPropertiesManager::AddServersData(
const base::DictionaryValue& servers_dict,
ServerList* spdy_servers,
@@ -780,6 +904,10 @@ void HttpServerPropertiesManager::UpdateCacheFromPrefsOnNetworkSequence(
IPAddress* last_quic_address,
ServerNetworkStatsMap* server_network_stats_map,
QuicServerInfoMap* quic_server_info_map,
+ std::unique_ptr<BrokenAlternativeServiceList>
+ broken_alternative_service_list,
+ std::unique_ptr<RecentlyBrokenAlternativeServices>
+ recently_broken_alternative_services,
bool detected_corrupted_prefs) {
// Preferences have the master data because admins might have pushed new
// preferences. Update the cached data with new data from preferences.
@@ -804,6 +932,13 @@ void HttpServerPropertiesManager::UpdateCacheFromPrefsOnNetworkSequence(
http_server_properties_impl_->SetQuicServerInfoMap(quic_server_info_map);
+ if (recently_broken_alternative_services) {
+ DCHECK(broken_alternative_service_list);
+ http_server_properties_impl_->AddBrokenAndRecentlyBrokenAlternativeServices(
+ std::move(broken_alternative_service_list),
+ std::move(recently_broken_alternative_services));
+ }
+
// Update the prefs with what we have read (delete all corrupted prefs).
if (detected_corrupted_prefs)
ScheduleUpdatePrefsOnNetworkSequence(DETECTED_CORRUPTED_PREFS);
@@ -869,9 +1004,6 @@ void HttpServerPropertiesManager::UpdatePrefsFromCacheOnNetworkSequence(
if (alternative_service.host.empty()) {
alternative_service.host = server.host();
}
- if (IsAlternativeServiceBroken(alternative_service)) {
- continue;
- }
notbroken_alternative_service_info_vector.push_back(
alternative_service_info);
}
@@ -915,6 +1047,41 @@ void HttpServerPropertiesManager::UpdatePrefsFromCacheOnNetworkSequence(
}
}
+ // Make copy of list of broken alternative services stored in
+ // |http_server_properties_impl_|
+ BrokenAlternativeServiceList* broken_alt_svc_list_copy = nullptr;
+ const BrokenAlternativeServiceList& broken_alternative_service_list =
+ http_server_properties_impl_->broken_alternative_service_list();
+ if (broken_alternative_service_list.size() > 0) {
+ broken_alt_svc_list_copy = new BrokenAlternativeServiceList();
+ size_t count = 0;
+ for (auto it = broken_alternative_service_list.begin();
+ it != broken_alternative_service_list.end() &&
+ count < kMaxBrokenAlternativeServicesToPersist;
+ ++it) {
+ broken_alt_svc_list_copy->push_back(*it);
+ ++count;
+ }
+ }
+
+ // Make copy of RecentlyBrokenAternativeServices stored in
+ // |http_server_properties_impl_|.
+ RecentlyBrokenAlternativeServices* recently_broken_alt_svc_copy = nullptr;
+ const RecentlyBrokenAlternativeServices& recently_broken_alt_services =
+ http_server_properties_impl_->recently_broken_alternative_services();
+ if (recently_broken_alt_services.size() > 0) {
+ recently_broken_alt_svc_copy = new RecentlyBrokenAlternativeServices(
+ kMaxRecentlyBrokenAlternativeServicesToPersist);
+ size_t count = 0;
+ for (auto it = recently_broken_alt_services.rbegin();
+ it != recently_broken_alt_services.rend() &&
+ count < kMaxRecentlyBrokenAlternativeServicesToPersist;
+ ++it) {
+ recently_broken_alt_svc_copy->Put(it->first, it->second);
+ ++count;
+ }
+ }
+
IPAddress* last_quic_addr = new IPAddress;
http_server_properties_impl_->GetSupportsQuic(last_quic_addr);
// Update the preferences on the pref thread.
@@ -924,7 +1091,9 @@ void HttpServerPropertiesManager::UpdatePrefsFromCacheOnNetworkSequence(
&HttpServerPropertiesManager::UpdatePrefsOnPrefThread, pref_weak_ptr_,
base::Owned(spdy_server_list), base::Owned(alternative_service_map),
base::Owned(last_quic_addr), base::Owned(server_network_stats_map),
- base::Owned(quic_server_info_map), completion));
+ base::Owned(quic_server_info_map),
+ base::Owned(broken_alt_svc_list_copy),
+ base::Owned(recently_broken_alt_svc_copy), completion));
}
// A local or temporary data structure to hold |supports_spdy|, SpdySettings,
@@ -962,6 +1131,8 @@ void HttpServerPropertiesManager::UpdatePrefsOnPrefThread(
IPAddress* last_quic_address,
ServerNetworkStatsMap* server_network_stats_map,
QuicServerInfoMap* quic_server_info_map,
+ BrokenAlternativeServiceList* broken_alternative_service_list,
+ RecentlyBrokenAlternativeServices* recently_broken_alternative_services,
const base::Closure& completion) {
typedef base::MRUCache<url::SchemeHostPort, ServerPref> ServerPrefMap;
ServerPrefMap server_pref_map(ServerPrefMap::NO_AUTO_EVICT);
@@ -1048,6 +1219,12 @@ void HttpServerPropertiesManager::UpdatePrefsOnPrefThread(
SaveQuicServerInfoMapToServerPrefs(quic_server_info_map,
&http_server_properties_dict);
+ SaveBrokenAlternativeServiceListToPrefs(broken_alternative_service_list,
+ &http_server_properties_dict);
+
+ SaveRecentlyBrokenAlternativeServicesToPrefs(
+ recently_broken_alternative_services, &http_server_properties_dict);
+
setting_prefs_ = true;
pref_delegate_->SetServerProperties(http_server_properties_dict);
setting_prefs_ = false;
@@ -1144,6 +1321,57 @@ void HttpServerPropertiesManager::SaveQuicServerInfoMapToServerPrefs(
kQuicServers, std::move(quic_servers_dict));
}
+void HttpServerPropertiesManager::SaveBrokenAlternativeServiceListToPrefs(
+ const BrokenAlternativeServiceList* broken_alternative_service_list,
+ base::DictionaryValue* http_server_properties_dict) {
+ if (!broken_alternative_service_list)
+ return;
+
+ base::ListValue* broken_alt_services_list = new base::ListValue;
+ for (const auto& entry : *broken_alternative_service_list) {
+ const AlternativeService& alt_service = entry.first;
+ const base::TimeTicks& expiration_time_ticks = entry.second;
+ // Convert expiration from TimeTicks to Time to time_t
+ time_t expiration_time_t =
+ (base::Time::Now() + (expiration_time_ticks - clock_->NowTicks()))
+ .ToTimeT();
+ int64_t expiration_int64 = static_cast<int64_t>(expiration_time_t);
+ std::unique_ptr<base::DictionaryValue> broken_alt_service_entry_dict =
+ base::MakeUnique<base::DictionaryValue>();
+ broken_alt_service_entry_dict->SetStringWithoutPathExpansion(
+ alt_service.ToString(), base::Int64ToString(expiration_int64));
+ broken_alt_services_list->Append(std::move(broken_alt_service_entry_dict));
+ }
+ http_server_properties_dict->SetWithoutPathExpansion(
+ kBrokenAlternativeServicesKey,
+ std::unique_ptr<base::Value>(broken_alt_services_list));
+}
+
+void HttpServerPropertiesManager::SaveRecentlyBrokenAlternativeServicesToPrefs(
+ const RecentlyBrokenAlternativeServices*
+ recently_broken_alternative_services,
+ base::DictionaryValue* http_server_properties_dict) {
+ if (!recently_broken_alternative_services)
+ return;
+
+ // JSON list will have entries ordered from least recent to most recent.
+ base::ListValue* recently_broken_alt_services_list = new base::ListValue;
+ for (auto it = recently_broken_alternative_services->rbegin();
+ it != recently_broken_alternative_services->rend(); ++it) {
+ const AlternativeService& alt_service = it->first;
+ int broken_count = it->second;
+ std::unique_ptr<base::DictionaryValue> broken_alt_service_entry_dict =
+ base::MakeUnique<base::DictionaryValue>();
+ broken_alt_service_entry_dict->SetIntegerWithoutPathExpansion(
+ alt_service.ToString(), broken_count);
+ recently_broken_alt_services_list->Append(
+ std::move(broken_alt_service_entry_dict));
+ }
+ http_server_properties_dict->SetWithoutPathExpansion(
+ kRecentlyBrokenAlternativeServicesKey,
+ std::unique_ptr<base::Value>(recently_broken_alt_services_list));
+}
+
void HttpServerPropertiesManager::OnHttpServerPropertiesChanged() {
DCHECK(pref_task_runner_->RunsTasksInCurrentSequence());
if (!setting_prefs_)
@@ -1155,4 +1383,13 @@ void HttpServerPropertiesManager::SetInitialized() {
is_initialized_ = true;
}
+void HttpServerPropertiesManager::SetTickClockForTesting(
+ base::TickClock* clock) {
+ DCHECK(clock);
+ DCHECK(http_server_properties_impl_);
+ clock_ = clock;
+ http_server_properties_impl_->SetBrokenAlternativeServicesTickClockForTesting(
+ clock);
+}
+
} // namespace net

Powered by Google App Engine
This is Rietveld 408576698