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