1 // Copyright 2012 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "net/http/http_server_properties.h"
6
7 #include "base/check_op.h"
8 #include "base/containers/adapters.h"
9 #include "base/containers/contains.h"
10 #include "base/feature_list.h"
11 #include "base/functional/bind.h"
12 #include "base/location.h"
13 #include "base/metrics/histogram_macros.h"
14 #include "base/strings/string_util.h"
15 #include "base/strings/stringprintf.h"
16 #include "base/task/single_thread_task_runner.h"
17 #include "base/time/default_clock.h"
18 #include "base/time/default_tick_clock.h"
19 #include "base/values.h"
20 #include "net/base/features.h"
21 #include "net/base/url_util.h"
22 #include "net/http/http_network_session.h"
23 #include "net/http/http_server_properties_manager.h"
24 #include "net/socket/ssl_client_socket.h"
25 #include "net/ssl/ssl_config.h"
26
27 namespace net {
28
29 namespace {
30
31 // Time to wait before starting an update the preferences from the
32 // http_server_properties_impl_ cache. Scheduling another update during this
33 // period will be a no-op.
34 constexpr base::TimeDelta kUpdatePrefsDelay = base::Seconds(60);
35
NormalizeSchemeHostPort(const url::SchemeHostPort & scheme_host_port)36 url::SchemeHostPort NormalizeSchemeHostPort(
37 const url::SchemeHostPort& scheme_host_port) {
38 if (scheme_host_port.scheme() == url::kWssScheme) {
39 return url::SchemeHostPort(url::kHttpsScheme, scheme_host_port.host(),
40 scheme_host_port.port());
41 }
42 if (scheme_host_port.scheme() == url::kWsScheme) {
43 return url::SchemeHostPort(url::kHttpScheme, scheme_host_port.host(),
44 scheme_host_port.port());
45 }
46 return scheme_host_port;
47 }
48
49 } // namespace
50
51 HttpServerProperties::PrefDelegate::~PrefDelegate() = default;
52
53 HttpServerProperties::ServerInfo::ServerInfo() = default;
54 HttpServerProperties::ServerInfo::ServerInfo(const ServerInfo& server_info) =
55 default;
56 HttpServerProperties::ServerInfo::ServerInfo(ServerInfo&& server_info) =
57 default;
58 HttpServerProperties::ServerInfo::~ServerInfo() = default;
59
empty() const60 bool HttpServerProperties::ServerInfo::empty() const {
61 return !supports_spdy.has_value() && !alternative_services.has_value() &&
62 !server_network_stats.has_value();
63 }
64
operator ==(const ServerInfo & other) const65 bool HttpServerProperties::ServerInfo::operator==(
66 const ServerInfo& other) const {
67 return supports_spdy == other.supports_spdy &&
68 alternative_services == other.alternative_services &&
69 server_network_stats == other.server_network_stats;
70 }
71
ServerInfoMapKey(url::SchemeHostPort server,const NetworkAnonymizationKey & network_anonymization_key,bool use_network_anonymization_key)72 HttpServerProperties::ServerInfoMapKey::ServerInfoMapKey(
73 url::SchemeHostPort server,
74 const NetworkAnonymizationKey& network_anonymization_key,
75 bool use_network_anonymization_key)
76 : server(std::move(server)),
77 network_anonymization_key(use_network_anonymization_key
78 ? network_anonymization_key
79 : NetworkAnonymizationKey()) {
80 // Scheme should have been normalized before this method was called.
81 DCHECK_NE(this->server.scheme(), url::kWsScheme);
82 DCHECK_NE(this->server.scheme(), url::kWssScheme);
83 }
84
85 HttpServerProperties::ServerInfoMapKey::~ServerInfoMapKey() = default;
86
operator <(const ServerInfoMapKey & other) const87 bool HttpServerProperties::ServerInfoMapKey::operator<(
88 const ServerInfoMapKey& other) const {
89 return std::tie(server, network_anonymization_key) <
90 std::tie(other.server, other.network_anonymization_key);
91 }
92
QuicServerInfoMapKey(const quic::QuicServerId & server_id,const NetworkAnonymizationKey & network_anonymization_key,bool use_network_anonymization_key)93 HttpServerProperties::QuicServerInfoMapKey::QuicServerInfoMapKey(
94 const quic::QuicServerId& server_id,
95 const NetworkAnonymizationKey& network_anonymization_key,
96 bool use_network_anonymization_key)
97 : server_id(server_id),
98 network_anonymization_key(use_network_anonymization_key
99 ? network_anonymization_key
100 : NetworkAnonymizationKey()) {}
101
102 HttpServerProperties::QuicServerInfoMapKey::~QuicServerInfoMapKey() = default;
103
operator <(const QuicServerInfoMapKey & other) const104 bool HttpServerProperties::QuicServerInfoMapKey::operator<(
105 const QuicServerInfoMapKey& other) const {
106 return std::tie(server_id, network_anonymization_key) <
107 std::tie(other.server_id, other.network_anonymization_key);
108 }
109
110 // Used in tests.
operator ==(const QuicServerInfoMapKey & other) const111 bool HttpServerProperties::QuicServerInfoMapKey::operator==(
112 const QuicServerInfoMapKey& other) const {
113 return std::tie(server_id, network_anonymization_key) ==
114 std::tie(other.server_id, other.network_anonymization_key);
115 }
116
ServerInfoMap()117 HttpServerProperties::ServerInfoMap::ServerInfoMap()
118 : base::LRUCache<ServerInfoMapKey, ServerInfo>(kMaxServerInfoEntries) {}
119
120 HttpServerProperties::ServerInfoMap::iterator
GetOrPut(const ServerInfoMapKey & key)121 HttpServerProperties::ServerInfoMap::GetOrPut(const ServerInfoMapKey& key) {
122 auto it = Get(key);
123 if (it != end())
124 return it;
125 return Put(key, ServerInfo());
126 }
127
128 HttpServerProperties::ServerInfoMap::iterator
EraseIfEmpty(iterator server_info_it)129 HttpServerProperties::ServerInfoMap::EraseIfEmpty(iterator server_info_it) {
130 if (server_info_it->second.empty())
131 return Erase(server_info_it);
132 return ++server_info_it;
133 }
134
HttpServerProperties(std::unique_ptr<PrefDelegate> pref_delegate,NetLog * net_log,const base::TickClock * tick_clock,base::Clock * clock)135 HttpServerProperties::HttpServerProperties(
136 std::unique_ptr<PrefDelegate> pref_delegate,
137 NetLog* net_log,
138 const base::TickClock* tick_clock,
139 base::Clock* clock)
140 : tick_clock_(tick_clock ? tick_clock
141 : base::DefaultTickClock::GetInstance()),
142 clock_(clock ? clock : base::DefaultClock::GetInstance()),
143 use_network_anonymization_key_(
144 NetworkAnonymizationKey::IsPartitioningEnabled()),
145 is_initialized_(pref_delegate.get() == nullptr),
146 properties_manager_(
147 pref_delegate
148 ? std::make_unique<HttpServerPropertiesManager>(
149 std::move(pref_delegate),
150 base::BindOnce(&HttpServerProperties::OnPrefsLoaded,
151 base::Unretained(this)),
152 kDefaultMaxQuicServerEntries,
153 net_log,
154 tick_clock_)
155 : nullptr),
156 broken_alternative_services_(kMaxRecentlyBrokenAlternativeServiceEntries,
157 this,
158 tick_clock_),
159 canonical_suffixes_({".ggpht.com", ".c.youtube.com", ".googlevideo.com",
160 ".googleusercontent.com", ".gvt1.com"}),
161 quic_server_info_map_(kDefaultMaxQuicServerEntries),
162 max_server_configs_stored_in_properties_(kDefaultMaxQuicServerEntries) {}
163
~HttpServerProperties()164 HttpServerProperties::~HttpServerProperties() {
165 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
166
167 if (properties_manager_) {
168 // Stop waiting for initial settings.
169 is_initialized_ = true;
170
171 // Stop the timer if it's running, since this will write to the properties
172 // file immediately.
173 prefs_update_timer_.Stop();
174
175 WriteProperties(base::OnceClosure());
176 }
177 }
178
Clear(base::OnceClosure callback)179 void HttpServerProperties::Clear(base::OnceClosure callback) {
180 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
181 server_info_map_.Clear();
182 broken_alternative_services_.Clear();
183 canonical_alt_svc_map_.clear();
184 last_local_address_when_quic_worked_ = IPAddress();
185 quic_server_info_map_.Clear();
186 canonical_server_info_map_.clear();
187
188 if (properties_manager_) {
189 // Stop waiting for initial settings.
190 is_initialized_ = true;
191 // Leaving this as-is doesn't actually have any effect, if it's true, but
192 // seems best to be safe.
193 queue_write_on_load_ = false;
194
195 // Stop the timer if it's running, since this will write to the properties
196 // file immediately.
197 prefs_update_timer_.Stop();
198 WriteProperties(std::move(callback));
199 } else if (callback) {
200 base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
201 FROM_HERE, std::move(callback));
202 }
203 }
204
SupportsRequestPriority(const url::SchemeHostPort & server,const net::NetworkAnonymizationKey & network_anonymization_key)205 bool HttpServerProperties::SupportsRequestPriority(
206 const url::SchemeHostPort& server,
207 const net::NetworkAnonymizationKey& network_anonymization_key) {
208 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
209 if (server.host().empty())
210 return false;
211
212 if (GetSupportsSpdy(server, network_anonymization_key))
213 return true;
214 const AlternativeServiceInfoVector alternative_service_info_vector =
215 GetAlternativeServiceInfos(server, network_anonymization_key);
216 for (const AlternativeServiceInfo& alternative_service_info :
217 alternative_service_info_vector) {
218 if (alternative_service_info.alternative_service().protocol == kProtoQUIC) {
219 return true;
220 }
221 }
222 return false;
223 }
224
GetSupportsSpdy(const url::SchemeHostPort & server,const net::NetworkAnonymizationKey & network_anonymization_key)225 bool HttpServerProperties::GetSupportsSpdy(
226 const url::SchemeHostPort& server,
227 const net::NetworkAnonymizationKey& network_anonymization_key) {
228 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
229 return GetSupportsSpdyInternal(NormalizeSchemeHostPort(server),
230 network_anonymization_key);
231 }
232
SetSupportsSpdy(const url::SchemeHostPort & server,const net::NetworkAnonymizationKey & network_anonymization_key,bool supports_spdy)233 void HttpServerProperties::SetSupportsSpdy(
234 const url::SchemeHostPort& server,
235 const net::NetworkAnonymizationKey& network_anonymization_key,
236 bool supports_spdy) {
237 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
238 SetSupportsSpdyInternal(NormalizeSchemeHostPort(server),
239 network_anonymization_key, supports_spdy);
240 }
241
RequiresHTTP11(const url::SchemeHostPort & server,const net::NetworkAnonymizationKey & network_anonymization_key)242 bool HttpServerProperties::RequiresHTTP11(
243 const url::SchemeHostPort& server,
244 const net::NetworkAnonymizationKey& network_anonymization_key) {
245 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
246 return RequiresHTTP11Internal(NormalizeSchemeHostPort(server),
247 network_anonymization_key);
248 }
249
SetHTTP11Required(const url::SchemeHostPort & server,const net::NetworkAnonymizationKey & network_anonymization_key)250 void HttpServerProperties::SetHTTP11Required(
251 const url::SchemeHostPort& server,
252 const net::NetworkAnonymizationKey& network_anonymization_key) {
253 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
254 SetHTTP11RequiredInternal(NormalizeSchemeHostPort(server),
255 network_anonymization_key);
256 }
257
MaybeForceHTTP11(const url::SchemeHostPort & server,const net::NetworkAnonymizationKey & network_anonymization_key,SSLConfig * ssl_config)258 void HttpServerProperties::MaybeForceHTTP11(
259 const url::SchemeHostPort& server,
260 const net::NetworkAnonymizationKey& network_anonymization_key,
261 SSLConfig* ssl_config) {
262 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
263 MaybeForceHTTP11Internal(NormalizeSchemeHostPort(server),
264 network_anonymization_key, ssl_config);
265 }
266
GetAlternativeServiceInfos(const url::SchemeHostPort & origin,const net::NetworkAnonymizationKey & network_anonymization_key)267 AlternativeServiceInfoVector HttpServerProperties::GetAlternativeServiceInfos(
268 const url::SchemeHostPort& origin,
269 const net::NetworkAnonymizationKey& network_anonymization_key) {
270 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
271 return GetAlternativeServiceInfosInternal(NormalizeSchemeHostPort(origin),
272 network_anonymization_key);
273 }
274
SetHttp2AlternativeService(const url::SchemeHostPort & origin,const NetworkAnonymizationKey & network_anonymization_key,const AlternativeService & alternative_service,base::Time expiration)275 void HttpServerProperties::SetHttp2AlternativeService(
276 const url::SchemeHostPort& origin,
277 const NetworkAnonymizationKey& network_anonymization_key,
278 const AlternativeService& alternative_service,
279 base::Time expiration) {
280 DCHECK_EQ(alternative_service.protocol, kProtoHTTP2);
281
282 SetAlternativeServices(
283 origin, network_anonymization_key,
284 AlternativeServiceInfoVector(
285 /*size=*/1, AlternativeServiceInfo::CreateHttp2AlternativeServiceInfo(
286 alternative_service, expiration)));
287 }
288
SetQuicAlternativeService(const url::SchemeHostPort & origin,const NetworkAnonymizationKey & network_anonymization_key,const AlternativeService & alternative_service,base::Time expiration,const quic::ParsedQuicVersionVector & advertised_versions)289 void HttpServerProperties::SetQuicAlternativeService(
290 const url::SchemeHostPort& origin,
291 const NetworkAnonymizationKey& network_anonymization_key,
292 const AlternativeService& alternative_service,
293 base::Time expiration,
294 const quic::ParsedQuicVersionVector& advertised_versions) {
295 DCHECK(alternative_service.protocol == kProtoQUIC);
296
297 SetAlternativeServices(
298 origin, network_anonymization_key,
299 AlternativeServiceInfoVector(
300 /*size=*/1,
301 AlternativeServiceInfo::CreateQuicAlternativeServiceInfo(
302 alternative_service, expiration, advertised_versions)));
303 }
304
SetAlternativeServices(const url::SchemeHostPort & origin,const net::NetworkAnonymizationKey & network_anonymization_key,const AlternativeServiceInfoVector & alternative_service_info_vector)305 void HttpServerProperties::SetAlternativeServices(
306 const url::SchemeHostPort& origin,
307 const net::NetworkAnonymizationKey& network_anonymization_key,
308 const AlternativeServiceInfoVector& alternative_service_info_vector) {
309 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
310 SetAlternativeServicesInternal(NormalizeSchemeHostPort(origin),
311 network_anonymization_key,
312 alternative_service_info_vector);
313 }
314
MarkAlternativeServiceBroken(const AlternativeService & alternative_service,const net::NetworkAnonymizationKey & network_anonymization_key)315 void HttpServerProperties::MarkAlternativeServiceBroken(
316 const AlternativeService& alternative_service,
317 const net::NetworkAnonymizationKey& network_anonymization_key) {
318 broken_alternative_services_.MarkBroken(
319 BrokenAlternativeService(alternative_service, network_anonymization_key,
320 use_network_anonymization_key_));
321 MaybeQueueWriteProperties();
322 }
323
324 void HttpServerProperties::
MarkAlternativeServiceBrokenUntilDefaultNetworkChanges(const AlternativeService & alternative_service,const net::NetworkAnonymizationKey & network_anonymization_key)325 MarkAlternativeServiceBrokenUntilDefaultNetworkChanges(
326 const AlternativeService& alternative_service,
327 const net::NetworkAnonymizationKey& network_anonymization_key) {
328 broken_alternative_services_.MarkBrokenUntilDefaultNetworkChanges(
329 BrokenAlternativeService(alternative_service, network_anonymization_key,
330 use_network_anonymization_key_));
331 MaybeQueueWriteProperties();
332 }
333
MarkAlternativeServiceRecentlyBroken(const AlternativeService & alternative_service,const net::NetworkAnonymizationKey & network_anonymization_key)334 void HttpServerProperties::MarkAlternativeServiceRecentlyBroken(
335 const AlternativeService& alternative_service,
336 const net::NetworkAnonymizationKey& network_anonymization_key) {
337 broken_alternative_services_.MarkRecentlyBroken(
338 BrokenAlternativeService(alternative_service, network_anonymization_key,
339 use_network_anonymization_key_));
340 MaybeQueueWriteProperties();
341 }
342
IsAlternativeServiceBroken(const AlternativeService & alternative_service,const net::NetworkAnonymizationKey & network_anonymization_key) const343 bool HttpServerProperties::IsAlternativeServiceBroken(
344 const AlternativeService& alternative_service,
345 const net::NetworkAnonymizationKey& network_anonymization_key) const {
346 return broken_alternative_services_.IsBroken(
347 BrokenAlternativeService(alternative_service, network_anonymization_key,
348 use_network_anonymization_key_));
349 }
350
WasAlternativeServiceRecentlyBroken(const AlternativeService & alternative_service,const net::NetworkAnonymizationKey & network_anonymization_key)351 bool HttpServerProperties::WasAlternativeServiceRecentlyBroken(
352 const AlternativeService& alternative_service,
353 const net::NetworkAnonymizationKey& network_anonymization_key) {
354 return broken_alternative_services_.WasRecentlyBroken(
355 BrokenAlternativeService(alternative_service, network_anonymization_key,
356 use_network_anonymization_key_));
357 }
358
ConfirmAlternativeService(const AlternativeService & alternative_service,const net::NetworkAnonymizationKey & network_anonymization_key)359 void HttpServerProperties::ConfirmAlternativeService(
360 const AlternativeService& alternative_service,
361 const net::NetworkAnonymizationKey& network_anonymization_key) {
362 bool old_value = IsAlternativeServiceBroken(alternative_service,
363 network_anonymization_key);
364 broken_alternative_services_.Confirm(
365 BrokenAlternativeService(alternative_service, network_anonymization_key,
366 use_network_anonymization_key_));
367 bool new_value = IsAlternativeServiceBroken(alternative_service,
368 network_anonymization_key);
369
370 // For persisting, we only care about the value returned by
371 // IsAlternativeServiceBroken. If that value changes, then call persist.
372 if (old_value != new_value)
373 MaybeQueueWriteProperties();
374 }
375
OnDefaultNetworkChanged()376 void HttpServerProperties::OnDefaultNetworkChanged() {
377 bool changed = broken_alternative_services_.OnDefaultNetworkChanged();
378 if (changed)
379 MaybeQueueWriteProperties();
380 }
381
GetAlternativeServiceInfoAsValue() const382 base::Value HttpServerProperties::GetAlternativeServiceInfoAsValue() const {
383 const base::Time now = clock_->Now();
384 const base::TimeTicks now_ticks = tick_clock_->NowTicks();
385 base::Value::List dict_list;
386 for (const auto& server_info : server_info_map_) {
387 if (!server_info.second.alternative_services.has_value())
388 continue;
389 base::Value::List alternative_service_list;
390 const ServerInfoMapKey& key = server_info.first;
391 for (const AlternativeServiceInfo& alternative_service_info :
392 server_info.second.alternative_services.value()) {
393 std::string alternative_service_string(
394 alternative_service_info.ToString());
395 AlternativeService alternative_service(
396 alternative_service_info.alternative_service());
397 if (alternative_service.host.empty()) {
398 alternative_service.host = key.server.host();
399 }
400 base::TimeTicks brokenness_expiration_ticks;
401 if (broken_alternative_services_.IsBroken(
402 BrokenAlternativeService(
403 alternative_service,
404 server_info.first.network_anonymization_key,
405 use_network_anonymization_key_),
406 &brokenness_expiration_ticks)) {
407 // Convert |brokenness_expiration| from TimeTicks to Time.
408 //
409 // Note: Cannot use `base::UnlocalizedTimeFormatWithPattern()` since
410 // `net/DEPS` disallows `base/i18n`.
411 base::Time brokenness_expiration =
412 now + (brokenness_expiration_ticks - now_ticks);
413 base::Time::Exploded exploded;
414 brokenness_expiration.LocalExplode(&exploded);
415 std::string broken_info_string =
416 " (broken until " +
417 base::StringPrintf("%04d-%02d-%02d %0d:%0d:%0d", exploded.year,
418 exploded.month, exploded.day_of_month,
419 exploded.hour, exploded.minute,
420 exploded.second) +
421 ")";
422 alternative_service_string.append(broken_info_string);
423 }
424 alternative_service_list.Append(std::move(alternative_service_string));
425 }
426 if (alternative_service_list.empty())
427 continue;
428 base::Value::Dict dict;
429 dict.Set("server", key.server.Serialize());
430 dict.Set("network_anonymization_key",
431 key.network_anonymization_key.ToDebugString());
432 dict.Set("alternative_service", std::move(alternative_service_list));
433 dict_list.Append(std::move(dict));
434 }
435 return base::Value(std::move(dict_list));
436 }
437
WasLastLocalAddressWhenQuicWorked(const IPAddress & local_address) const438 bool HttpServerProperties::WasLastLocalAddressWhenQuicWorked(
439 const IPAddress& local_address) const {
440 return !last_local_address_when_quic_worked_.empty() &&
441 last_local_address_when_quic_worked_ == local_address;
442 }
443
HasLastLocalAddressWhenQuicWorked() const444 bool HttpServerProperties::HasLastLocalAddressWhenQuicWorked() const {
445 return !last_local_address_when_quic_worked_.empty();
446 }
447
SetLastLocalAddressWhenQuicWorked(IPAddress last_local_address_when_quic_worked)448 void HttpServerProperties::SetLastLocalAddressWhenQuicWorked(
449 IPAddress last_local_address_when_quic_worked) {
450 DCHECK(!last_local_address_when_quic_worked.empty());
451 if (last_local_address_when_quic_worked_ ==
452 last_local_address_when_quic_worked) {
453 return;
454 }
455
456 last_local_address_when_quic_worked_ = last_local_address_when_quic_worked;
457 MaybeQueueWriteProperties();
458 }
459
ClearLastLocalAddressWhenQuicWorked()460 void HttpServerProperties::ClearLastLocalAddressWhenQuicWorked() {
461 if (last_local_address_when_quic_worked_.empty())
462 return;
463
464 last_local_address_when_quic_worked_ = IPAddress();
465 MaybeQueueWriteProperties();
466 }
467
SetServerNetworkStats(const url::SchemeHostPort & server,const NetworkAnonymizationKey & network_anonymization_key,ServerNetworkStats stats)468 void HttpServerProperties::SetServerNetworkStats(
469 const url::SchemeHostPort& server,
470 const NetworkAnonymizationKey& network_anonymization_key,
471 ServerNetworkStats stats) {
472 SetServerNetworkStatsInternal(NormalizeSchemeHostPort(server),
473 network_anonymization_key, std::move(stats));
474 }
475
ClearServerNetworkStats(const url::SchemeHostPort & server,const NetworkAnonymizationKey & network_anonymization_key)476 void HttpServerProperties::ClearServerNetworkStats(
477 const url::SchemeHostPort& server,
478 const NetworkAnonymizationKey& network_anonymization_key) {
479 ClearServerNetworkStatsInternal(NormalizeSchemeHostPort(server),
480 network_anonymization_key);
481 }
482
GetServerNetworkStats(const url::SchemeHostPort & server,const NetworkAnonymizationKey & network_anonymization_key)483 const ServerNetworkStats* HttpServerProperties::GetServerNetworkStats(
484 const url::SchemeHostPort& server,
485 const NetworkAnonymizationKey& network_anonymization_key) {
486 return GetServerNetworkStatsInternal(NormalizeSchemeHostPort(server),
487 network_anonymization_key);
488 }
489
SetQuicServerInfo(const quic::QuicServerId & server_id,const NetworkAnonymizationKey & network_anonymization_key,const std::string & server_info)490 void HttpServerProperties::SetQuicServerInfo(
491 const quic::QuicServerId& server_id,
492 const NetworkAnonymizationKey& network_anonymization_key,
493 const std::string& server_info) {
494 QuicServerInfoMapKey key =
495 CreateQuicServerInfoKey(server_id, network_anonymization_key);
496 auto it = quic_server_info_map_.Peek(key);
497 bool changed =
498 (it == quic_server_info_map_.end() || it->second != server_info);
499 quic_server_info_map_.Put(key, server_info);
500 UpdateCanonicalServerInfoMap(key);
501 if (changed)
502 MaybeQueueWriteProperties();
503 }
504
GetQuicServerInfo(const quic::QuicServerId & server_id,const NetworkAnonymizationKey & network_anonymization_key)505 const std::string* HttpServerProperties::GetQuicServerInfo(
506 const quic::QuicServerId& server_id,
507 const NetworkAnonymizationKey& network_anonymization_key) {
508 QuicServerInfoMapKey key =
509 CreateQuicServerInfoKey(server_id, network_anonymization_key);
510 auto it = quic_server_info_map_.Get(key);
511 if (it != quic_server_info_map_.end()) {
512 // Since |canonical_server_info_map_| should always map to the most
513 // recent host, update it with the one that became MRU in
514 // |quic_server_info_map_|.
515 UpdateCanonicalServerInfoMap(key);
516 return &it->second;
517 }
518
519 // If the exact match for |server_id| wasn't found, check
520 // |canonical_server_info_map_| whether there is server info for a host with
521 // the same canonical host suffix.
522 auto canonical_itr = GetCanonicalServerInfoHost(key);
523 if (canonical_itr == canonical_server_info_map_.end())
524 return nullptr;
525
526 // When search in |quic_server_info_map_|, do not change the MRU order.
527 it = quic_server_info_map_.Peek(CreateQuicServerInfoKey(
528 canonical_itr->second, network_anonymization_key));
529 if (it != quic_server_info_map_.end())
530 return &it->second;
531
532 return nullptr;
533 }
534
535 const HttpServerProperties::QuicServerInfoMap&
quic_server_info_map() const536 HttpServerProperties::quic_server_info_map() const {
537 return quic_server_info_map_;
538 }
539
max_server_configs_stored_in_properties() const540 size_t HttpServerProperties::max_server_configs_stored_in_properties() const {
541 return max_server_configs_stored_in_properties_;
542 }
543
SetMaxServerConfigsStoredInProperties(size_t max_server_configs_stored_in_properties)544 void HttpServerProperties::SetMaxServerConfigsStoredInProperties(
545 size_t max_server_configs_stored_in_properties) {
546 // Do nothing if the new size is the same as the old one.
547 if (max_server_configs_stored_in_properties_ ==
548 max_server_configs_stored_in_properties) {
549 return;
550 }
551
552 max_server_configs_stored_in_properties_ =
553 max_server_configs_stored_in_properties;
554
555 // LRUCache doesn't allow the capacity of the cache to be changed. Thus create
556 // a new map with the new size and add current elements and swap the new map.
557 quic_server_info_map_.ShrinkToSize(max_server_configs_stored_in_properties_);
558 QuicServerInfoMap temp_map(max_server_configs_stored_in_properties_);
559 // Update the |canonical_server_info_map_| as well, so it stays in sync with
560 // |quic_server_info_map_|.
561 canonical_server_info_map_ = QuicCanonicalMap();
562 for (const auto& [key, server_info] : base::Reversed(quic_server_info_map_)) {
563 temp_map.Put(key, server_info);
564 UpdateCanonicalServerInfoMap(key);
565 }
566
567 quic_server_info_map_.Swap(temp_map);
568 if (properties_manager_) {
569 properties_manager_->set_max_server_configs_stored_in_properties(
570 max_server_configs_stored_in_properties);
571 }
572 }
573
SetBrokenAlternativeServicesDelayParams(absl::optional<base::TimeDelta> initial_delay,absl::optional<bool> exponential_backoff_on_initial_delay)574 void HttpServerProperties::SetBrokenAlternativeServicesDelayParams(
575 absl::optional<base::TimeDelta> initial_delay,
576 absl::optional<bool> exponential_backoff_on_initial_delay) {
577 broken_alternative_services_.SetDelayParams(
578 initial_delay, exponential_backoff_on_initial_delay);
579 }
580
IsInitialized() const581 bool HttpServerProperties::IsInitialized() const {
582 return is_initialized_;
583 }
584
OnExpireBrokenAlternativeService(const AlternativeService & expired_alternative_service,const NetworkAnonymizationKey & network_anonymization_key)585 void HttpServerProperties::OnExpireBrokenAlternativeService(
586 const AlternativeService& expired_alternative_service,
587 const NetworkAnonymizationKey& network_anonymization_key) {
588 // Remove every occurrence of |expired_alternative_service| from
589 // |alternative_service_map_|.
590 for (auto map_it = server_info_map_.begin();
591 map_it != server_info_map_.end();) {
592 if (!map_it->second.alternative_services.has_value() ||
593 map_it->first.network_anonymization_key != network_anonymization_key) {
594 ++map_it;
595 continue;
596 }
597 AlternativeServiceInfoVector* service_info =
598 &map_it->second.alternative_services.value();
599 for (auto it = service_info->begin(); it != service_info->end();) {
600 AlternativeService alternative_service(it->alternative_service());
601 // Empty hostname in map means hostname of key: substitute before
602 // comparing to |expired_alternative_service|.
603 if (alternative_service.host.empty()) {
604 alternative_service.host = map_it->first.server.host();
605 }
606 if (alternative_service == expired_alternative_service) {
607 it = service_info->erase(it);
608 continue;
609 }
610 ++it;
611 }
612 // If an origin has an empty list of alternative services, then remove it
613 // from both |canonical_alt_svc_map_| and
614 // |alternative_service_map_|.
615 if (service_info->empty()) {
616 RemoveAltSvcCanonicalHost(map_it->first.server,
617 network_anonymization_key);
618 map_it->second.alternative_services.reset();
619 map_it = server_info_map_.EraseIfEmpty(map_it);
620 continue;
621 }
622 ++map_it;
623 }
624 }
625
GetUpdatePrefsDelayForTesting()626 base::TimeDelta HttpServerProperties::GetUpdatePrefsDelayForTesting() {
627 return kUpdatePrefsDelay;
628 }
629
GetSupportsSpdyInternal(url::SchemeHostPort server,const net::NetworkAnonymizationKey & network_anonymization_key)630 bool HttpServerProperties::GetSupportsSpdyInternal(
631 url::SchemeHostPort server,
632 const net::NetworkAnonymizationKey& network_anonymization_key) {
633 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
634 DCHECK_NE(server.scheme(), url::kWsScheme);
635 DCHECK_NE(server.scheme(), url::kWssScheme);
636 if (server.host().empty())
637 return false;
638
639 auto server_info = server_info_map_.Get(
640 CreateServerInfoKey(std::move(server), network_anonymization_key));
641 return server_info != server_info_map_.end() &&
642 server_info->second.supports_spdy.value_or(false);
643 }
644
SetSupportsSpdyInternal(url::SchemeHostPort server,const net::NetworkAnonymizationKey & network_anonymization_key,bool supports_spdy)645 void HttpServerProperties::SetSupportsSpdyInternal(
646 url::SchemeHostPort server,
647 const net::NetworkAnonymizationKey& network_anonymization_key,
648 bool supports_spdy) {
649 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
650 DCHECK_NE(server.scheme(), url::kWsScheme);
651 DCHECK_NE(server.scheme(), url::kWssScheme);
652 if (server.host().empty())
653 return;
654
655 auto server_info = server_info_map_.GetOrPut(
656 CreateServerInfoKey(std::move(server), network_anonymization_key));
657 // If value is already the same as |supports_spdy|, or value is unset and
658 // |supports_spdy| is false, don't queue a write.
659 bool queue_write =
660 server_info->second.supports_spdy.value_or(false) != supports_spdy;
661 server_info->second.supports_spdy = supports_spdy;
662
663 if (queue_write)
664 MaybeQueueWriteProperties();
665 }
666
RequiresHTTP11Internal(url::SchemeHostPort server,const net::NetworkAnonymizationKey & network_anonymization_key)667 bool HttpServerProperties::RequiresHTTP11Internal(
668 url::SchemeHostPort server,
669 const net::NetworkAnonymizationKey& network_anonymization_key) {
670 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
671 DCHECK_NE(server.scheme(), url::kWsScheme);
672 DCHECK_NE(server.scheme(), url::kWssScheme);
673 if (server.host().empty())
674 return false;
675
676 auto spdy_info = server_info_map_.Get(
677 CreateServerInfoKey(std::move(server), network_anonymization_key));
678 return spdy_info != server_info_map_.end() &&
679 spdy_info->second.requires_http11.value_or(false);
680 }
681
SetHTTP11RequiredInternal(url::SchemeHostPort server,const net::NetworkAnonymizationKey & network_anonymization_key)682 void HttpServerProperties::SetHTTP11RequiredInternal(
683 url::SchemeHostPort server,
684 const net::NetworkAnonymizationKey& network_anonymization_key) {
685 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
686 DCHECK_NE(server.scheme(), url::kWsScheme);
687 DCHECK_NE(server.scheme(), url::kWssScheme);
688 if (server.host().empty())
689 return;
690
691 server_info_map_
692 .GetOrPut(
693 CreateServerInfoKey(std::move(server), network_anonymization_key))
694 ->second.requires_http11 = true;
695 // No need to call MaybeQueueWriteProperties(), as this information is not
696 // persisted to preferences.
697 }
698
MaybeForceHTTP11Internal(url::SchemeHostPort server,const net::NetworkAnonymizationKey & network_anonymization_key,SSLConfig * ssl_config)699 void HttpServerProperties::MaybeForceHTTP11Internal(
700 url::SchemeHostPort server,
701 const net::NetworkAnonymizationKey& network_anonymization_key,
702 SSLConfig* ssl_config) {
703 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
704 DCHECK_NE(server.scheme(), url::kWsScheme);
705 DCHECK_NE(server.scheme(), url::kWssScheme);
706 if (RequiresHTTP11(std::move(server), network_anonymization_key)) {
707 ssl_config->alpn_protos.clear();
708 ssl_config->alpn_protos.push_back(kProtoHTTP11);
709 }
710 }
711
712 AlternativeServiceInfoVector
GetAlternativeServiceInfosInternal(const url::SchemeHostPort & origin,const net::NetworkAnonymizationKey & network_anonymization_key)713 HttpServerProperties::GetAlternativeServiceInfosInternal(
714 const url::SchemeHostPort& origin,
715 const net::NetworkAnonymizationKey& network_anonymization_key) {
716 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
717 DCHECK_NE(origin.scheme(), url::kWsScheme);
718 DCHECK_NE(origin.scheme(), url::kWssScheme);
719
720 // Copy valid alternative service infos into
721 // |valid_alternative_service_infos|.
722 AlternativeServiceInfoVector valid_alternative_service_infos;
723 const base::Time now = clock_->Now();
724 auto map_it = server_info_map_.Get(
725 CreateServerInfoKey(origin, network_anonymization_key));
726 if (map_it != server_info_map_.end() &&
727 map_it->second.alternative_services.has_value()) {
728 AlternativeServiceInfoVector* service_info =
729 &map_it->second.alternative_services.value();
730 HostPortPair host_port_pair(origin.host(), origin.port());
731 for (auto it = service_info->begin(); it != service_info->end();) {
732 if (it->expiration() < now) {
733 it = service_info->erase(it);
734 continue;
735 }
736 AlternativeService alternative_service(it->alternative_service());
737 if (alternative_service.host.empty()) {
738 alternative_service.host = origin.host();
739 }
740 // If the alternative service is equivalent to the origin (same host, same
741 // port, and both TCP), skip it.
742 if (host_port_pair.Equals(alternative_service.host_port_pair()) &&
743 alternative_service.protocol == kProtoHTTP2) {
744 ++it;
745 continue;
746 }
747 if (alternative_service.protocol == kProtoQUIC) {
748 valid_alternative_service_infos.push_back(
749 AlternativeServiceInfo::CreateQuicAlternativeServiceInfo(
750 alternative_service, it->expiration(),
751 it->advertised_versions()));
752 } else {
753 valid_alternative_service_infos.push_back(
754 AlternativeServiceInfo::CreateHttp2AlternativeServiceInfo(
755 alternative_service, it->expiration()));
756 }
757 ++it;
758 }
759 if (service_info->empty()) {
760 map_it->second.alternative_services.reset();
761 server_info_map_.EraseIfEmpty(map_it);
762 }
763 return valid_alternative_service_infos;
764 }
765
766 auto canonical = GetCanonicalAltSvcHost(origin, network_anonymization_key);
767 if (canonical == canonical_alt_svc_map_.end()) {
768 return AlternativeServiceInfoVector();
769 }
770 map_it = server_info_map_.Get(
771 CreateServerInfoKey(canonical->second, network_anonymization_key));
772 if (map_it == server_info_map_.end() ||
773 !map_it->second.alternative_services.has_value()) {
774 return AlternativeServiceInfoVector();
775 }
776 AlternativeServiceInfoVector* service_info =
777 &map_it->second.alternative_services.value();
778 for (auto it = service_info->begin(); it != service_info->end();) {
779 if (it->expiration() < now) {
780 it = service_info->erase(it);
781 continue;
782 }
783 AlternativeService alternative_service(it->alternative_service());
784 if (alternative_service.host.empty()) {
785 alternative_service.host = canonical->second.host();
786 if (IsAlternativeServiceBroken(alternative_service,
787 network_anonymization_key)) {
788 ++it;
789 continue;
790 }
791 alternative_service.host = origin.host();
792 } else if (IsAlternativeServiceBroken(alternative_service,
793 network_anonymization_key)) {
794 ++it;
795 continue;
796 }
797 if (alternative_service.protocol == kProtoQUIC) {
798 valid_alternative_service_infos.push_back(
799 AlternativeServiceInfo::CreateQuicAlternativeServiceInfo(
800 alternative_service, it->expiration(),
801 it->advertised_versions()));
802 } else {
803 valid_alternative_service_infos.push_back(
804 AlternativeServiceInfo::CreateHttp2AlternativeServiceInfo(
805 alternative_service, it->expiration()));
806 }
807 ++it;
808 }
809 if (service_info->empty())
810 server_info_map_.EraseIfEmpty(map_it);
811 return valid_alternative_service_infos;
812 }
813
SetAlternativeServicesInternal(const url::SchemeHostPort & origin,const net::NetworkAnonymizationKey & network_anonymization_key,const AlternativeServiceInfoVector & alternative_service_info_vector)814 void HttpServerProperties::SetAlternativeServicesInternal(
815 const url::SchemeHostPort& origin,
816 const net::NetworkAnonymizationKey& network_anonymization_key,
817 const AlternativeServiceInfoVector& alternative_service_info_vector) {
818 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
819 DCHECK_NE(origin.scheme(), url::kWsScheme);
820 DCHECK_NE(origin.scheme(), url::kWssScheme);
821
822 if (alternative_service_info_vector.empty()) {
823 RemoveAltSvcCanonicalHost(origin, network_anonymization_key);
824 // Don't bother moving to front when erasing information.
825 auto it = server_info_map_.Peek(
826 CreateServerInfoKey(origin, network_anonymization_key));
827
828 if (it == server_info_map_.end() ||
829 !it->second.alternative_services.has_value()) {
830 return;
831 }
832
833 it->second.alternative_services.reset();
834 server_info_map_.EraseIfEmpty(it);
835 MaybeQueueWriteProperties();
836 return;
837 }
838
839 auto it = server_info_map_.GetOrPut(
840 CreateServerInfoKey(origin, network_anonymization_key));
841 bool need_update_pref = true;
842 if (it->second.alternative_services.has_value()) {
843 DCHECK(!it->second.empty());
844 if (it->second.alternative_services->size() ==
845 alternative_service_info_vector.size()) {
846 const base::Time now = clock_->Now();
847 need_update_pref = false;
848 auto new_it = alternative_service_info_vector.begin();
849 for (const auto& old : *it->second.alternative_services) {
850 // Persist to disk immediately if new entry has different scheme, host,
851 // or port.
852 if (old.alternative_service() != new_it->alternative_service()) {
853 need_update_pref = true;
854 break;
855 }
856 // Also persist to disk if new expiration it more that twice as far or
857 // less than half as far in the future.
858 base::Time old_time = old.expiration();
859 base::Time new_time = new_it->expiration();
860 if (new_time - now > 2 * (old_time - now) ||
861 2 * (new_time - now) < (old_time - now)) {
862 need_update_pref = true;
863 break;
864 }
865 // Also persist to disk if new entry has a different list of advertised
866 // versions.
867 if (old.advertised_versions() != new_it->advertised_versions()) {
868 need_update_pref = true;
869 break;
870 }
871 ++new_it;
872 }
873 }
874 }
875
876 const bool previously_no_alternative_services =
877 (GetIteratorWithAlternativeServiceInfo(
878 origin, network_anonymization_key) == server_info_map_.end());
879
880 it->second.alternative_services = alternative_service_info_vector;
881
882 if (previously_no_alternative_services &&
883 !GetAlternativeServiceInfos(origin, network_anonymization_key).empty()) {
884 // TODO(rch): Consider the case where multiple requests are started
885 // before the first completes. In this case, only one of the jobs
886 // would reach this code, whereas all of them should should have.
887 HistogramAlternateProtocolUsage(ALTERNATE_PROTOCOL_USAGE_MAPPING_MISSING,
888 IsGoogleHost(origin.host()));
889 }
890
891 // If this host ends with a canonical suffix, then set it as the
892 // canonical host.
893 const char* kCanonicalScheme = "https";
894 if (origin.scheme() == kCanonicalScheme) {
895 const std::string* canonical_suffix = GetCanonicalSuffix(origin.host());
896 if (canonical_suffix != nullptr) {
897 url::SchemeHostPort canonical_server(kCanonicalScheme, *canonical_suffix,
898 origin.port());
899 canonical_alt_svc_map_[CreateServerInfoKey(
900 canonical_server, network_anonymization_key)] = origin;
901 }
902 }
903
904 if (need_update_pref)
905 MaybeQueueWriteProperties();
906 }
907
SetServerNetworkStatsInternal(url::SchemeHostPort server,const NetworkAnonymizationKey & network_anonymization_key,ServerNetworkStats stats)908 void HttpServerProperties::SetServerNetworkStatsInternal(
909 url::SchemeHostPort server,
910 const NetworkAnonymizationKey& network_anonymization_key,
911 ServerNetworkStats stats) {
912 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
913 DCHECK_NE(server.scheme(), url::kWsScheme);
914 DCHECK_NE(server.scheme(), url::kWssScheme);
915
916 auto server_info = server_info_map_.GetOrPut(
917 CreateServerInfoKey(std::move(server), network_anonymization_key));
918 bool changed = !server_info->second.server_network_stats.has_value() ||
919 server_info->second.server_network_stats.value() != stats;
920
921 if (changed) {
922 server_info->second.server_network_stats = stats;
923 MaybeQueueWriteProperties();
924 }
925 }
926
ClearServerNetworkStatsInternal(url::SchemeHostPort server,const NetworkAnonymizationKey & network_anonymization_key)927 void HttpServerProperties::ClearServerNetworkStatsInternal(
928 url::SchemeHostPort server,
929 const NetworkAnonymizationKey& network_anonymization_key) {
930 auto server_info = server_info_map_.Peek(
931 CreateServerInfoKey(std::move(server), network_anonymization_key));
932 // If stats are empty, nothing to do.
933 if (server_info == server_info_map_.end() ||
934 !server_info->second.server_network_stats.has_value()) {
935 return;
936 }
937
938 // Otherwise, clear and delete if needed. No need to bring to front of MRU
939 // cache when clearing data.
940 server_info->second.server_network_stats.reset();
941 if (server_info->second.empty())
942 server_info_map_.EraseIfEmpty(server_info);
943 MaybeQueueWriteProperties();
944 }
945
GetServerNetworkStatsInternal(url::SchemeHostPort server,const NetworkAnonymizationKey & network_anonymization_key)946 const ServerNetworkStats* HttpServerProperties::GetServerNetworkStatsInternal(
947 url::SchemeHostPort server,
948 const NetworkAnonymizationKey& network_anonymization_key) {
949 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
950 DCHECK_NE(server.scheme(), url::kWsScheme);
951 DCHECK_NE(server.scheme(), url::kWssScheme);
952
953 auto server_info = server_info_map_.Get(
954 CreateServerInfoKey(std::move(server), network_anonymization_key));
955 if (server_info == server_info_map_.end() ||
956 !server_info->second.server_network_stats.has_value()) {
957 return nullptr;
958 }
959 return &server_info->second.server_network_stats.value();
960 }
961
962 HttpServerProperties::QuicServerInfoMapKey
CreateQuicServerInfoKey(const quic::QuicServerId & server_id,const NetworkAnonymizationKey & network_anonymization_key) const963 HttpServerProperties::CreateQuicServerInfoKey(
964 const quic::QuicServerId& server_id,
965 const NetworkAnonymizationKey& network_anonymization_key) const {
966 return QuicServerInfoMapKey(server_id, network_anonymization_key,
967 use_network_anonymization_key_);
968 }
969
970 HttpServerProperties::ServerInfoMapKey
CreateServerInfoKey(const url::SchemeHostPort & server,const NetworkAnonymizationKey & network_anonymization_key) const971 HttpServerProperties::CreateServerInfoKey(
972 const url::SchemeHostPort& server,
973 const NetworkAnonymizationKey& network_anonymization_key) const {
974 return ServerInfoMapKey(server, network_anonymization_key,
975 use_network_anonymization_key_);
976 }
977
978 HttpServerProperties::ServerInfoMap::const_iterator
GetIteratorWithAlternativeServiceInfo(const url::SchemeHostPort & server,const net::NetworkAnonymizationKey & network_anonymization_key)979 HttpServerProperties::GetIteratorWithAlternativeServiceInfo(
980 const url::SchemeHostPort& server,
981 const net::NetworkAnonymizationKey& network_anonymization_key) {
982 ServerInfoMap::const_iterator it = server_info_map_.Get(
983 CreateServerInfoKey(server, network_anonymization_key));
984 if (it != server_info_map_.end() && it->second.alternative_services)
985 return it;
986
987 auto canonical = GetCanonicalAltSvcHost(server, network_anonymization_key);
988 if (canonical == canonical_alt_svc_map_.end()) {
989 return server_info_map_.end();
990 }
991
992 const url::SchemeHostPort canonical_server = canonical->second;
993 it = server_info_map_.Get(
994 CreateServerInfoKey(canonical_server, network_anonymization_key));
995 if (it == server_info_map_.end() || !it->second.alternative_services)
996 return server_info_map_.end();
997
998 for (const AlternativeServiceInfo& alternative_service_info :
999 it->second.alternative_services.value()) {
1000 AlternativeService alternative_service(
1001 alternative_service_info.alternative_service());
1002 if (alternative_service.host.empty()) {
1003 alternative_service.host = canonical_server.host();
1004 }
1005 if (!IsAlternativeServiceBroken(alternative_service,
1006 network_anonymization_key)) {
1007 return it;
1008 }
1009 }
1010
1011 RemoveAltSvcCanonicalHost(canonical_server, network_anonymization_key);
1012 return server_info_map_.end();
1013 }
1014
1015 HttpServerProperties::CanonicalMap::const_iterator
GetCanonicalAltSvcHost(const url::SchemeHostPort & server,const net::NetworkAnonymizationKey & network_anonymization_key) const1016 HttpServerProperties::GetCanonicalAltSvcHost(
1017 const url::SchemeHostPort& server,
1018 const net::NetworkAnonymizationKey& network_anonymization_key) const {
1019 const char* kCanonicalScheme = "https";
1020 if (server.scheme() != kCanonicalScheme)
1021 return canonical_alt_svc_map_.end();
1022
1023 const std::string* canonical_suffix = GetCanonicalSuffix(server.host());
1024 if (canonical_suffix == nullptr)
1025 return canonical_alt_svc_map_.end();
1026
1027 url::SchemeHostPort canonical_server(kCanonicalScheme, *canonical_suffix,
1028 server.port());
1029 return canonical_alt_svc_map_.find(
1030 CreateServerInfoKey(canonical_server, network_anonymization_key));
1031 }
1032
1033 HttpServerProperties::QuicCanonicalMap::const_iterator
GetCanonicalServerInfoHost(const QuicServerInfoMapKey & key) const1034 HttpServerProperties::GetCanonicalServerInfoHost(
1035 const QuicServerInfoMapKey& key) const {
1036 const std::string* canonical_suffix =
1037 GetCanonicalSuffix(key.server_id.host());
1038 if (canonical_suffix == nullptr)
1039 return canonical_server_info_map_.end();
1040
1041 quic::QuicServerId canonical_server_id(*canonical_suffix,
1042 key.server_id.privacy_mode_enabled(),
1043 key.server_id.port());
1044 return canonical_server_info_map_.find(CreateQuicServerInfoKey(
1045 canonical_server_id, key.network_anonymization_key));
1046 }
1047
RemoveAltSvcCanonicalHost(const url::SchemeHostPort & server,const NetworkAnonymizationKey & network_anonymization_key)1048 void HttpServerProperties::RemoveAltSvcCanonicalHost(
1049 const url::SchemeHostPort& server,
1050 const NetworkAnonymizationKey& network_anonymization_key) {
1051 auto canonical = GetCanonicalAltSvcHost(server, network_anonymization_key);
1052 if (canonical == canonical_alt_svc_map_.end())
1053 return;
1054
1055 canonical_alt_svc_map_.erase(canonical->first);
1056 }
1057
UpdateCanonicalServerInfoMap(const QuicServerInfoMapKey & key)1058 void HttpServerProperties::UpdateCanonicalServerInfoMap(
1059 const QuicServerInfoMapKey& key) {
1060 const std::string* suffix = GetCanonicalSuffix(key.server_id.host());
1061 if (!suffix)
1062 return;
1063 quic::QuicServerId canonical_server(
1064 *suffix, key.server_id.privacy_mode_enabled(), key.server_id.port());
1065
1066 canonical_server_info_map_[CreateQuicServerInfoKey(
1067 canonical_server, key.network_anonymization_key)] = key.server_id;
1068 }
1069
GetCanonicalSuffix(const std::string & host) const1070 const std::string* HttpServerProperties::GetCanonicalSuffix(
1071 const std::string& host) const {
1072 // If this host ends with a canonical suffix, then return the canonical
1073 // suffix.
1074 for (const std::string& canonical_suffix : canonical_suffixes_) {
1075 if (base::EndsWith(host, canonical_suffix,
1076 base::CompareCase::INSENSITIVE_ASCII)) {
1077 return &canonical_suffix;
1078 }
1079 }
1080 return nullptr;
1081 }
1082
OnPrefsLoaded(std::unique_ptr<ServerInfoMap> server_info_map,const IPAddress & last_local_address_when_quic_worked,std::unique_ptr<QuicServerInfoMap> quic_server_info_map,std::unique_ptr<BrokenAlternativeServiceList> broken_alternative_service_list,std::unique_ptr<RecentlyBrokenAlternativeServices> recently_broken_alternative_services)1083 void HttpServerProperties::OnPrefsLoaded(
1084 std::unique_ptr<ServerInfoMap> server_info_map,
1085 const IPAddress& last_local_address_when_quic_worked,
1086 std::unique_ptr<QuicServerInfoMap> quic_server_info_map,
1087 std::unique_ptr<BrokenAlternativeServiceList>
1088 broken_alternative_service_list,
1089 std::unique_ptr<RecentlyBrokenAlternativeServices>
1090 recently_broken_alternative_services) {
1091 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
1092
1093 DCHECK(!is_initialized_);
1094
1095 // Either all of these are nullptr, or none of them are (except the broken alt
1096 // service fields).
1097 if (server_info_map) {
1098 OnServerInfoLoaded(std::move(server_info_map));
1099 OnLastLocalAddressWhenQuicWorkedLoaded(last_local_address_when_quic_worked);
1100 OnQuicServerInfoMapLoaded(std::move(quic_server_info_map));
1101 if (recently_broken_alternative_services) {
1102 DCHECK(broken_alternative_service_list);
1103 OnBrokenAndRecentlyBrokenAlternativeServicesLoaded(
1104 std::move(broken_alternative_service_list),
1105 std::move(recently_broken_alternative_services));
1106 }
1107 }
1108
1109 is_initialized_ = true;
1110
1111 if (queue_write_on_load_) {
1112 // Leaving this as true doesn't actually have any effect, but seems best to
1113 // be safe.
1114 queue_write_on_load_ = false;
1115 MaybeQueueWriteProperties();
1116 }
1117 }
1118
OnServerInfoLoaded(std::unique_ptr<ServerInfoMap> server_info_map)1119 void HttpServerProperties::OnServerInfoLoaded(
1120 std::unique_ptr<ServerInfoMap> server_info_map) {
1121 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
1122
1123 // Perform a simple sanity check on loaded data, when DCHECKs are enabled.
1124 #if DCHECK_IS_ON()
1125 if (!use_network_anonymization_key_) {
1126 for (auto server_info = server_info_map->begin();
1127 server_info != server_info_map->end(); ++server_info) {
1128 DCHECK(server_info->first.network_anonymization_key.IsEmpty());
1129 }
1130 }
1131 #endif // DCHECK_IS_ON()
1132
1133 // Swap in the entries from persisted data. This allows the MRU cache to be
1134 // sorted based on the order of the entries in the newer in-memory cache.
1135 server_info_map_.Swap(*server_info_map);
1136
1137 // Add the entries from the memory cache.
1138 for (auto& [key, server_info] : base::Reversed(*server_info_map)) {
1139 // If there's no corresponding old entry, add the new entry directly.
1140 auto old_entry = server_info_map_.Get(key);
1141 if (old_entry == server_info_map_.end()) {
1142 server_info_map_.Put(key, std::move(server_info));
1143 continue;
1144 }
1145
1146 // Otherwise, merge the old and new entries. Prefer values from older
1147 // entries.
1148 if (!old_entry->second.supports_spdy.has_value())
1149 old_entry->second.supports_spdy = server_info.supports_spdy;
1150 if (!old_entry->second.alternative_services.has_value())
1151 old_entry->second.alternative_services = server_info.alternative_services;
1152 if (!old_entry->second.server_network_stats.has_value())
1153 old_entry->second.server_network_stats = server_info.server_network_stats;
1154
1155 // |requires_http11| isn't saved to prefs, so the loaded entry should not
1156 // have it set. Unconditionally copy it from the new entry.
1157 DCHECK(!old_entry->second.requires_http11.has_value());
1158 old_entry->second.requires_http11 = server_info.requires_http11;
1159 }
1160
1161 // Attempt to find canonical servers. Canonical suffix only apply to HTTPS.
1162 const uint16_t kCanonicalPort = 443;
1163 const char* kCanonicalScheme = "https";
1164 for (const auto& it : server_info_map_) {
1165 if (!it.second.alternative_services ||
1166 it.first.server.scheme() != kCanonicalScheme) {
1167 continue;
1168 }
1169 const std::string* canonical_suffix =
1170 GetCanonicalSuffix(it.first.server.host());
1171 if (!canonical_suffix)
1172 continue;
1173 ServerInfoMapKey key = CreateServerInfoKey(
1174 url::SchemeHostPort(kCanonicalScheme, *canonical_suffix,
1175 kCanonicalPort),
1176 it.first.network_anonymization_key);
1177 // If we already have a valid canonical server, we're done.
1178 if (base::Contains(canonical_alt_svc_map_, key)) {
1179 auto key_it = server_info_map_.Peek(key);
1180 if (key_it != server_info_map_.end() &&
1181 key_it->second.alternative_services.has_value()) {
1182 continue;
1183 }
1184 }
1185 canonical_alt_svc_map_[key] = it.first.server;
1186 }
1187 }
1188
OnLastLocalAddressWhenQuicWorkedLoaded(const IPAddress & last_local_address_when_quic_worked)1189 void HttpServerProperties::OnLastLocalAddressWhenQuicWorkedLoaded(
1190 const IPAddress& last_local_address_when_quic_worked) {
1191 last_local_address_when_quic_worked_ = last_local_address_when_quic_worked;
1192 }
1193
OnQuicServerInfoMapLoaded(std::unique_ptr<QuicServerInfoMap> quic_server_info_map)1194 void HttpServerProperties::OnQuicServerInfoMapLoaded(
1195 std::unique_ptr<QuicServerInfoMap> quic_server_info_map) {
1196 DCHECK_EQ(quic_server_info_map->max_size(), quic_server_info_map_.max_size());
1197
1198 // Add the entries from persisted data.
1199 quic_server_info_map_.Swap(*quic_server_info_map);
1200
1201 // Add the entries from the memory cache.
1202 for (const auto& [key, server_info] : base::Reversed(*quic_server_info_map)) {
1203 if (quic_server_info_map_.Get(key) == quic_server_info_map_.end()) {
1204 quic_server_info_map_.Put(key, server_info);
1205 }
1206 }
1207
1208 // Repopulate |canonical_server_info_map_| to stay in sync with
1209 // |quic_server_info_map_|.
1210 canonical_server_info_map_.clear();
1211 for (const auto& [key, server_info] : base::Reversed(quic_server_info_map_)) {
1212 UpdateCanonicalServerInfoMap(key);
1213 }
1214 }
1215
OnBrokenAndRecentlyBrokenAlternativeServicesLoaded(std::unique_ptr<BrokenAlternativeServiceList> broken_alternative_service_list,std::unique_ptr<RecentlyBrokenAlternativeServices> recently_broken_alternative_services)1216 void HttpServerProperties::OnBrokenAndRecentlyBrokenAlternativeServicesLoaded(
1217 std::unique_ptr<BrokenAlternativeServiceList>
1218 broken_alternative_service_list,
1219 std::unique_ptr<RecentlyBrokenAlternativeServices>
1220 recently_broken_alternative_services) {
1221 broken_alternative_services_.SetBrokenAndRecentlyBrokenAlternativeServices(
1222 std::move(broken_alternative_service_list),
1223 std::move(recently_broken_alternative_services));
1224 }
1225
MaybeQueueWriteProperties()1226 void HttpServerProperties::MaybeQueueWriteProperties() {
1227 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
1228 if (prefs_update_timer_.IsRunning() || !properties_manager_)
1229 return;
1230
1231 if (!is_initialized_) {
1232 queue_write_on_load_ = true;
1233 return;
1234 }
1235
1236 prefs_update_timer_.Start(
1237 FROM_HERE, kUpdatePrefsDelay,
1238 base::BindOnce(&HttpServerProperties::WriteProperties,
1239 base::Unretained(this), base::OnceClosure()));
1240 }
1241
FlushWritePropertiesForTesting(base::OnceClosure callback)1242 void HttpServerProperties::FlushWritePropertiesForTesting(
1243 base::OnceClosure callback) {
1244 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
1245 if (!properties_manager_) {
1246 return;
1247 }
1248
1249 // initialising the |properties_manager_| is not a concern here. So skip
1250 // it and set |is_initalized_| to true.
1251 is_initialized_ = true;
1252 // Stop the timer if it's running, since this will write to the properties
1253 // file immediately.
1254 prefs_update_timer_.Stop();
1255 WriteProperties(std::move(callback));
1256 }
1257
WriteProperties(base::OnceClosure callback) const1258 void HttpServerProperties::WriteProperties(base::OnceClosure callback) const {
1259 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
1260 DCHECK(properties_manager_);
1261
1262 // |this| shouldn't be waiting to load properties cached to disk when this
1263 // method is invoked, since this method will overwrite any cached properties.
1264 DCHECK(is_initialized_);
1265
1266 // There shouldn't be a queued update when this is run, since this method
1267 // removes the need for any update to be queued.
1268 DCHECK(!prefs_update_timer_.IsRunning());
1269
1270 properties_manager_->WriteToPrefs(
1271 server_info_map_,
1272 base::BindRepeating(&HttpServerProperties::GetCanonicalSuffix,
1273 base::Unretained(this)),
1274 last_local_address_when_quic_worked_, quic_server_info_map_,
1275 broken_alternative_services_.broken_alternative_service_list(),
1276 broken_alternative_services_.recently_broken_alternative_services(),
1277 std::move(callback));
1278 }
1279
1280 } // namespace net
1281