Commit 977f0279 authored by Matt Menke's avatar Matt Menke Committed by Commit Bot

HttpServerProperties: Hook NetworkIsolationKeys to broken alt service API

This CL makes HttpServerProperties methods that deal with broken alt
services take NetworkIsolationKeys, and wires through through to the
BrokenAlternativeServices object it owns. This CL also updates
HttpServerPropertiesManager to save/load the NetworkIsolationKey
associated with each broken alt service.

Bug: 969890
Change-Id: I81909c8a3965d510fe775e7ccadebd4d88e5a7da
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1775260
Commit-Queue: Matt Menke <mmenke@chromium.org>
Reviewed-by: default avatarZhongyi Shi <zhongyi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#695200}
parent 4b1282ab
...@@ -113,12 +113,6 @@ NET_EXPORT_PRIVATE std::ostream& operator<<( ...@@ -113,12 +113,6 @@ NET_EXPORT_PRIVATE std::ostream& operator<<(
std::ostream& os, std::ostream& os,
const AlternativeService& alternative_service); const AlternativeService& alternative_service);
struct AlternativeServiceHash {
size_t operator()(const net::AlternativeService& entry) const {
return entry.protocol ^ std::hash<std::string>()(entry.host) ^ entry.port;
}
};
class NET_EXPORT_PRIVATE AlternativeServiceInfo { class NET_EXPORT_PRIVATE AlternativeServiceInfo {
public: public:
static AlternativeServiceInfo CreateHttp2AlternativeServiceInfo( static AlternativeServiceInfo CreateHttp2AlternativeServiceInfo(
......
...@@ -487,46 +487,52 @@ void HttpServerProperties::SetAlternativeServices( ...@@ -487,46 +487,52 @@ void HttpServerProperties::SetAlternativeServices(
} }
void HttpServerProperties::MarkAlternativeServiceBroken( void HttpServerProperties::MarkAlternativeServiceBroken(
const AlternativeService& alternative_service) { const AlternativeService& alternative_service,
const net::NetworkIsolationKey& network_isolation_key) {
broken_alternative_services_.MarkBroken(BrokenAlternativeService( broken_alternative_services_.MarkBroken(BrokenAlternativeService(
alternative_service, NetworkIsolationKey(), use_network_isolation_key_)); alternative_service, network_isolation_key, use_network_isolation_key_));
MaybeQueueWriteProperties(); MaybeQueueWriteProperties();
} }
void HttpServerProperties:: void HttpServerProperties::
MarkAlternativeServiceBrokenUntilDefaultNetworkChanges( MarkAlternativeServiceBrokenUntilDefaultNetworkChanges(
const AlternativeService& alternative_service) { const AlternativeService& alternative_service,
const net::NetworkIsolationKey& network_isolation_key) {
broken_alternative_services_.MarkBrokenUntilDefaultNetworkChanges( broken_alternative_services_.MarkBrokenUntilDefaultNetworkChanges(
BrokenAlternativeService(alternative_service, NetworkIsolationKey(), BrokenAlternativeService(alternative_service, network_isolation_key,
use_network_isolation_key_)); use_network_isolation_key_));
MaybeQueueWriteProperties(); MaybeQueueWriteProperties();
} }
void HttpServerProperties::MarkAlternativeServiceRecentlyBroken( void HttpServerProperties::MarkAlternativeServiceRecentlyBroken(
const AlternativeService& alternative_service) { const AlternativeService& alternative_service,
const net::NetworkIsolationKey& network_isolation_key) {
broken_alternative_services_.MarkRecentlyBroken(BrokenAlternativeService( broken_alternative_services_.MarkRecentlyBroken(BrokenAlternativeService(
alternative_service, NetworkIsolationKey(), use_network_isolation_key_)); alternative_service, network_isolation_key, use_network_isolation_key_));
MaybeQueueWriteProperties(); MaybeQueueWriteProperties();
} }
bool HttpServerProperties::IsAlternativeServiceBroken( bool HttpServerProperties::IsAlternativeServiceBroken(
const AlternativeService& alternative_service) const { const AlternativeService& alternative_service,
const net::NetworkIsolationKey& network_isolation_key) const {
return broken_alternative_services_.IsBroken(BrokenAlternativeService( return broken_alternative_services_.IsBroken(BrokenAlternativeService(
alternative_service, NetworkIsolationKey(), use_network_isolation_key_)); alternative_service, network_isolation_key, use_network_isolation_key_));
} }
bool HttpServerProperties::WasAlternativeServiceRecentlyBroken( bool HttpServerProperties::WasAlternativeServiceRecentlyBroken(
const AlternativeService& alternative_service) { const AlternativeService& alternative_service,
const net::NetworkIsolationKey& network_isolation_key) {
return broken_alternative_services_.WasRecentlyBroken( return broken_alternative_services_.WasRecentlyBroken(
BrokenAlternativeService(alternative_service, NetworkIsolationKey(), BrokenAlternativeService(alternative_service, network_isolation_key,
use_network_isolation_key_)); use_network_isolation_key_));
} }
void HttpServerProperties::ConfirmAlternativeService( void HttpServerProperties::ConfirmAlternativeService(
const AlternativeService& alternative_service) { const AlternativeService& alternative_service,
const net::NetworkIsolationKey& network_isolation_key) {
bool old_value = IsAlternativeServiceBroken(alternative_service); bool old_value = IsAlternativeServiceBroken(alternative_service);
broken_alternative_services_.Confirm(BrokenAlternativeService( broken_alternative_services_.Confirm(BrokenAlternativeService(
alternative_service, NetworkIsolationKey(), use_network_isolation_key_)); alternative_service, network_isolation_key, use_network_isolation_key_));
bool new_value = IsAlternativeServiceBroken(alternative_service); bool new_value = IsAlternativeServiceBroken(alternative_service);
// For persisting, we only care about the value returned by // For persisting, we only care about the value returned by
......
...@@ -297,34 +297,48 @@ class NET_EXPORT HttpServerProperties ...@@ -297,34 +297,48 @@ class NET_EXPORT HttpServerProperties
const net::NetworkIsolationKey& network_isolation_key, const net::NetworkIsolationKey& network_isolation_key,
const AlternativeServiceInfoVector& alternative_service_info_vector); const AlternativeServiceInfoVector& alternative_service_info_vector);
// Marks |alternative_service| as broken. // Marks |alternative_service| as broken in the context of
// |alternative_service.host| must not be empty. // |network_isolation_key|. |alternative_service.host| must not be empty.
void MarkAlternativeServiceBroken( void MarkAlternativeServiceBroken(
const AlternativeService& alternative_service); const AlternativeService& alternative_service,
const net::NetworkIsolationKey& network_isolation_key =
NetworkIsolationKey());
// Marks |alternative_service| as broken until the default network changes. // Marks |alternative_service| as broken in the context of
// |network_isolation_key| until the default network changes.
// |alternative_service.host| must not be empty. // |alternative_service.host| must not be empty.
void MarkAlternativeServiceBrokenUntilDefaultNetworkChanges( void MarkAlternativeServiceBrokenUntilDefaultNetworkChanges(
const AlternativeService& alternative_service); const AlternativeService& alternative_service,
const net::NetworkIsolationKey& network_isolation_key =
NetworkIsolationKey());
// Marks |alternative_service| as recently broken. // Marks |alternative_service| as recently broken in the context of
// |alternative_service.host| must not be empty. // |network_isolation_key|. |alternative_service.host| must not be empty.
void MarkAlternativeServiceRecentlyBroken( void MarkAlternativeServiceRecentlyBroken(
const AlternativeService& alternative_service); const AlternativeService& alternative_service,
const net::NetworkIsolationKey& network_isolation_key =
NetworkIsolationKey());
// Returns true iff |alternative_service| is currently broken. // Returns true iff |alternative_service| is currently broken in the context
// |alternative_service.host| must not be empty. // of |network_isolation_key|. |alternative_service.host| must not be empty.
bool IsAlternativeServiceBroken( bool IsAlternativeServiceBroken(
const AlternativeService& alternative_service) const; const AlternativeService& alternative_service,
const net::NetworkIsolationKey& network_isolation_key =
NetworkIsolationKey()) const;
// Returns true iff |alternative_service| was recently broken. // Returns true iff |alternative_service| was recently broken in the context
// |alternative_service.host| must not be empty. // of |network_isolation_key|. |alternative_service.host| must not be empty.
bool WasAlternativeServiceRecentlyBroken( bool WasAlternativeServiceRecentlyBroken(
const AlternativeService& alternative_service); const AlternativeService& alternative_service,
const net::NetworkIsolationKey& network_isolation_key =
NetworkIsolationKey());
// Confirms that |alternative_service| is working. // Confirms that |alternative_service| is working in the context of
// |alternative_service.host| must not be empty. // |network_isolation_key|. |alternative_service.host| must not be empty.
void ConfirmAlternativeService(const AlternativeService& alternative_service); void ConfirmAlternativeService(
const AlternativeService& alternative_service,
const net::NetworkIsolationKey& network_isolation_key =
NetworkIsolationKey());
// Called when the default network changes. // Called when the default network changes.
// Clears all the alternative services that were marked broken until the // Clears all the alternative services that were marked broken until the
......
...@@ -113,6 +113,23 @@ void AddAlternativeServiceFieldsToDictionaryValue( ...@@ -113,6 +113,23 @@ void AddAlternativeServiceFieldsToDictionaryValue(
NextProtoToString(alternative_service.protocol)); NextProtoToString(alternative_service.protocol));
} }
// Fails in the case of NetworkIsolationKeys that can't be persisted to disk,
// like unique origins.
bool TryAddBrokenAlternativeServiceFieldsToDictionaryValue(
const BrokenAlternativeService& broken_alt_service,
base::DictionaryValue* dict) {
base::Value network_isolation_key_value;
if (!broken_alt_service.network_isolation_key.ToValue(
&network_isolation_key_value)) {
return false;
}
dict->SetKey(kNetworkIsolationKey, std::move(network_isolation_key_value));
AddAlternativeServiceFieldsToDictionaryValue(
broken_alt_service.alternative_service, dict);
return true;
}
quic::QuicServerId QuicServerIdFromString(const std::string& str) { quic::QuicServerId QuicServerIdFromString(const std::string& str) {
GURL url(str); GURL url(str);
if (!url.is_valid()) { if (!url.is_valid()) {
...@@ -298,6 +315,20 @@ void HttpServerPropertiesManager::AddToBrokenAlternativeServices( ...@@ -298,6 +315,20 @@ void HttpServerPropertiesManager::AddToBrokenAlternativeServices(
return; return;
} }
const base::Value* network_isolation_key_value =
broken_alt_svc_entry_dict.FindKey(kNetworkIsolationKey);
NetworkIsolationKey network_isolation_key;
if (!network_isolation_key_value ||
!NetworkIsolationKey::FromValue(*network_isolation_key_value,
&network_isolation_key)) {
return;
}
// Fail if NetworkIsolationKeys are disabled, but the entry has a non-empty
// NetworkIsolationKey.
if (!use_network_isolation_key && !network_isolation_key.IsEmpty())
return;
// Each entry must contain either broken-count and/or broken-until fields. // Each entry must contain either broken-count and/or broken-until fields.
bool contains_broken_count_or_broken_until = false; bool contains_broken_count_or_broken_until = false;
...@@ -316,7 +347,7 @@ void HttpServerPropertiesManager::AddToBrokenAlternativeServices( ...@@ -316,7 +347,7 @@ void HttpServerPropertiesManager::AddToBrokenAlternativeServices(
return; return;
} }
recently_broken_alternative_services->Put( recently_broken_alternative_services->Put(
BrokenAlternativeService(alt_service, NetworkIsolationKey(), BrokenAlternativeService(alt_service, network_isolation_key,
use_network_isolation_key), use_network_isolation_key),
broken_count); broken_count);
contains_broken_count_or_broken_until = true; contains_broken_count_or_broken_until = true;
...@@ -341,7 +372,7 @@ void HttpServerPropertiesManager::AddToBrokenAlternativeServices( ...@@ -341,7 +372,7 @@ void HttpServerPropertiesManager::AddToBrokenAlternativeServices(
clock_->NowTicks() + clock_->NowTicks() +
(base::Time::FromTimeT(expiration_time_t) - base::Time::Now()); (base::Time::FromTimeT(expiration_time_t) - base::Time::Now());
broken_alternative_service_list->push_back(std::make_pair( broken_alternative_service_list->push_back(std::make_pair(
BrokenAlternativeService(alt_service, NetworkIsolationKey(), BrokenAlternativeService(alt_service, network_isolation_key,
use_network_isolation_key), use_network_isolation_key),
expiration_time_ticks)); expiration_time_ticks));
contains_broken_count_or_broken_until = true; contains_broken_count_or_broken_until = true;
...@@ -804,8 +835,9 @@ void HttpServerPropertiesManager::SaveBrokenAlternativeServicesToPrefs( ...@@ -804,8 +835,9 @@ void HttpServerPropertiesManager::SaveBrokenAlternativeServicesToPrefs(
recently_broken_alternative_services, recently_broken_alternative_services,
base::DictionaryValue* http_server_properties_dict) { base::DictionaryValue* http_server_properties_dict) {
if (broken_alternative_service_list.empty() && if (broken_alternative_service_list.empty() &&
recently_broken_alternative_services.empty()) recently_broken_alternative_services.empty()) {
return; return;
}
// JSON list will be in MRU order according to // JSON list will be in MRU order according to
// |recently_broken_alternative_services|. // |recently_broken_alternative_services|.
...@@ -814,20 +846,21 @@ void HttpServerPropertiesManager::SaveBrokenAlternativeServicesToPrefs( ...@@ -814,20 +846,21 @@ void HttpServerPropertiesManager::SaveBrokenAlternativeServicesToPrefs(
// Maps recently-broken alternative services to the index where it's stored // Maps recently-broken alternative services to the index where it's stored
// in |json_list|. // in |json_list|.
std::unordered_map<AlternativeService, size_t, AlternativeServiceHash> std::map<BrokenAlternativeService, size_t> json_list_index_map;
json_list_index_map;
if (!recently_broken_alternative_services.empty()) { if (!recently_broken_alternative_services.empty()) {
for (auto it = recently_broken_alternative_services.rbegin(); for (auto it = recently_broken_alternative_services.rbegin();
it != recently_broken_alternative_services.rend(); ++it) { it != recently_broken_alternative_services.rend(); ++it) {
const BrokenAlternativeService& broken_alt_service_info = it->first; const BrokenAlternativeService& broken_alt_service = it->first;
int broken_count = it->second; int broken_count = it->second;
base::DictionaryValue entry_dict; base::DictionaryValue entry_dict;
AddAlternativeServiceFieldsToDictionaryValue( if (!TryAddBrokenAlternativeServiceFieldsToDictionaryValue(
broken_alt_service_info.alternative_service, &entry_dict); broken_alt_service, &entry_dict)) {
continue;
}
entry_dict.SetKey(kBrokenCountKey, base::Value(broken_count)); entry_dict.SetKey(kBrokenCountKey, base::Value(broken_count));
json_list_index_map[broken_alt_service_info.alternative_service] = json_list_index_map[broken_alt_service] = json_list->GetList().size();
json_list->GetList().size();
json_list->GetList().push_back(std::move(entry_dict)); json_list->GetList().push_back(std::move(entry_dict));
} }
} }
...@@ -848,8 +881,7 @@ void HttpServerPropertiesManager::SaveBrokenAlternativeServicesToPrefs( ...@@ -848,8 +881,7 @@ void HttpServerPropertiesManager::SaveBrokenAlternativeServicesToPrefs(
.ToTimeT(); .ToTimeT();
int64_t expiration_int64 = static_cast<int64_t>(expiration_time_t); int64_t expiration_int64 = static_cast<int64_t>(expiration_time_t);
auto index_map_it = auto index_map_it = json_list_index_map.find(broken_alt_service);
json_list_index_map.find(broken_alt_service.alternative_service);
if (index_map_it != json_list_index_map.end()) { if (index_map_it != json_list_index_map.end()) {
size_t json_list_index = index_map_it->second; size_t json_list_index = index_map_it->second;
base::DictionaryValue* entry_dict = nullptr; base::DictionaryValue* entry_dict = nullptr;
...@@ -860,8 +892,10 @@ void HttpServerPropertiesManager::SaveBrokenAlternativeServicesToPrefs( ...@@ -860,8 +892,10 @@ void HttpServerPropertiesManager::SaveBrokenAlternativeServicesToPrefs(
base::Value(base::NumberToString(expiration_int64))); base::Value(base::NumberToString(expiration_int64)));
} else { } else {
base::DictionaryValue entry_dict; base::DictionaryValue entry_dict;
AddAlternativeServiceFieldsToDictionaryValue( if (!TryAddBrokenAlternativeServiceFieldsToDictionaryValue(
broken_alt_service.alternative_service, &entry_dict); broken_alt_service, &entry_dict)) {
continue;
}
entry_dict.SetKey(kBrokenUntilKey, entry_dict.SetKey(kBrokenUntilKey,
base::Value(base::NumberToString(expiration_int64))); base::Value(base::NumberToString(expiration_int64)));
json_list->GetList().push_back(std::move(entry_dict)); json_list->GetList().push_back(std::move(entry_dict));
...@@ -869,7 +903,11 @@ void HttpServerPropertiesManager::SaveBrokenAlternativeServicesToPrefs( ...@@ -869,7 +903,11 @@ void HttpServerPropertiesManager::SaveBrokenAlternativeServicesToPrefs(
} }
} }
DCHECK(!json_list->empty()); // This can happen if all the entries are for NetworkIsolationKeys for opaque
// origins, which isn't exactly common, but can theoretically happen.
if (json_list->empty())
return;
http_server_properties_dict->SetWithoutPathExpansion( http_server_properties_dict->SetWithoutPathExpansion(
kBrokenAlternativeServicesKey, std::move(json_list)); kBrokenAlternativeServicesKey, std::move(json_list));
} }
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment